Câu hỏi Nhận giá trị int từ enum trong C #


Tôi có một lớp được gọi là Questions (số nhiều). Trong lớp này có một enum gọi là Question (số ít) trông như thế này

public enum Question
{
    Role = 2,
    ProjectFunding = 3,
    TotalEmployee = 4,
    NumberOfServers = 5,
    TopBusinessConcern = 6
}

bên trong Questions lớp, tôi có một get(int foo) hàm trả về Questions đối tượng cho rằng foo. Có một cách dễ dàng để có được giá trị số nguyên từ enum vì vậy tôi có thể làm một cái gì đó như Questions.Get(Question.Role)?


1374
2018-06-03 06:46


gốc


Đối với các cách khác xung quanh: cast-int-to-enum-in-c-sắc nét. - nawfal
Tôi biết tôi đến muộn bên, nhưng thay vì xác định phương pháp của bạn get(int foo) bạn có thể định nghĩa nó là get(Question foo) sau đó thực hiện phép đúc của bạn bên trong phương thức, bạn có thể gọi phương thức của mình là Questions.Get(Question.Role) - Joe


Các câu trả lời:


Chỉ cần đúc enum, ví dụ:

int something = (int) Question.Role;

Ở trên sẽ làm việc cho đại đa số các enums bạn thấy trong tự nhiên, như là loại cơ bản mặc định cho một enum là int.

Tuy nhiên, như cecilphillip chỉ ra, enums có thể có các loại cơ bản khác nhau. Nếu một enum được khai báo là uint, long, hoặc là ulong, nó nên được đúc thành loại enum; ví dụ. cho

enum StarsInMilkyWay:long {Sun = 1, V645Centauri = 2 .. Wolf424B = 2147483649};

bạn nên sử dụng

long something = (long)StarsInMilkyWay.Wolf424B;

1803
2018-06-03 06:49



Ồ, thôi nào, tôi có enum Test { Item = (int)1 } và tôi phải dùng nó cho mỗi lần sử dụng? Xấu hổ trình biên dịch không thể làm điều đó cho tôi. Nó sẽ hoạt động như chuyển đổi ngầm định. Nhưng tất nhiên là không. - Harry
@ Harry nó không phải là sự thật. Bạn có thể tạo Enumeration mà không cần truyền, nó không được yêu cầu. và tôi chỉ gán số trong trường hợp đặc biệt, phần lớn thời gian, tôi để nó ở dạng giá trị mặc định. nhưng bạn có thể làm enum Test { Item = 1 } và thấy rằng 1 == (int)Test.Item bằng nhau. - Jaider
@Jaider (int)Test.Item Đó là một diễn viên! () là toán tử cast rõ ràng. - Sinthia V
@Sinthia V anh ấy nói bạn có thể tạo nên nó mà không cần đúc, đó là chính xác - Paul Ridgway
Nếu loại cơ bản cho enum Question không phải int nhưng long dàn diễn viên này sẽ cắt ngắn Rolegiá trị tích phân s! - quaylar


Vì Enums có thể là bất kỳ loại tích phân nào (byte, int, short, vv), một cách mạnh mẽ hơn để có được giá trị tích phân cơ bản của enum sẽ là sử dụng GetTypeCode phương pháp kết hợp với Convert lớp học:

enum Sides {
    Left, Right, Top, Bottom
}
Sides side = Sides.Bottom;

object val = Convert.ChangeType(side, side.GetTypeCode());
Console.WriteLine(val);

Điều này sẽ làm việc bất kể loại tích phân cơ bản.


237
2017-07-09 14:54



Kỹ thuật này đã chứng minh giá trị của nó đối với tôi khi đối phó với một loại chung mà T: enum (thực sự là T: struct, IConvertible nhưng đó là một câu chuyện khác). - aboy021
Làm thế nào bạn sẽ sửa đổi điều này để in ra giá trị thập lục phân của bên? Ví dụ này cho thấy giá trị thập phân. Vấn đề là ở đó var thuộc loại object, vì vậy bạn cần phải unbox nó và nó được messier hơn tôi muốn. - Mark Lakata
Tôi nghĩ bạn nên thay đổi ví dụ thành object val = Convert...etc các var trong ví dụ của bạn sẽ luôn là object. - Meshette
@TimAbell Tất cả những gì tôi thực sự có thể nói là chúng tôi thấy rằng các trang aspx được biên dịch động (nơi bạn phải triển khai các tệp .cs đến máy chủ trực tiếp) đã gán các số nguyên khác nhau cho mỗi giá trị. Điều đó có nghĩa rằng các đối tượng được tuần tự hóa một máy, đã được deserialising với các giá trị khác nhau trên một máy khác nhau và có hiệu quả bị hỏng (gây ra giờ nhầm lẫn). Chúng tôi đã nêu ra nó với MS và tôi dường như nhớ lại họ nói rằng các số nguyên tự sinh không được đảm bảo là giống nhau khi được xây dựng trên các phiên bản khung khác nhau. - NickG
@TimAbell Trong một dịp riêng biệt, một nhà phát triển đã xóa một giá trị Enum lỗi thời / không sử dụng khiến tất cả các giá trị khác trong chuỗi bị xóa bởi một. Do đó, các tiêu chuẩn mã hóa của chúng tôi hiện yêu cầu ID luôn được chỉ định rõ ràng, nếu không việc thêm / xóa hoặc thậm chí tự động định dạng mã (ví dụ: sắp xếp theo thứ tự bảng chữ cái) sẽ thay đổi tất cả các giá trị gây hỏng dữ liệu. Tôi mạnh mẽ sẽ khuyên bất cứ ai để xác định tất cả các số nguyên Enum một cách rõ ràng. Điều này cực kỳ quan trọng nếu chúng tương quan với các giá trị được lưu trữ bên ngoài (cơ sở dữ liệu). - NickG


Khai báo nó như là một lớp tĩnh có hằng số công khai:

public static class Question
{
    public const int Role = 2;
    public const int ProjectFunding = 3;
    public const int TotalEmployee = 4;
    public const int NumberOfServers = 5;
    public const int TopBusinessConcern = 6;
}

Và sau đó bạn có thể tham khảo nó như Question.Rolevà nó luôn luôn đánh giá int hoặc bất cứ điều gì bạn định nghĩa nó.


162
2018-06-15 19:28



Tôi ngạc nhiên rằng điều này không có nhiều phiếu bầu hơn - điều này hiển nhiên nếu bạn thực sự muốn sử dụng kiểu int. - CAD bloke
Tôi muốn dùng static readonly int bởi vì các hằng số được biên dịch thành các giá trị cứng của chúng. Xem stackoverflow.com/a/755693/492 - CAD bloke
Giải pháp này thực sự không cung cấp lợi ích thực sự của enums mạnh mẽ đánh máy. Nếu tôi chỉ muốn truyền tham số GameState-enum đến một phương thức cụ thể, trình biên dịch không cho phép tôi chuyển bất kỳ biến int nào thành tham số. - thgc
@CADBloke, đó chính xác là lý do bạn sẽ sử dụng const và không static readonly bởi vì mỗi khi bạn so sánh static readonly bạn đang thực hiện cuộc gọi phương thức để nhận giá trị của biến trong khi với const bạn đang so sánh trực tiếp hai loại giá trị. - blockloop
@ brettof86 Có, một const sẽ nhanh hơn, nếu giới hạn biên dịch sẽ không bao giờ là vấn đề thì tất cả đều tốt. - CAD bloke


Question question = Question.Role;
int value = (int) question;

Sẽ cho kết quả value == 2.


72
2018-06-03 06:48



Câu hỏi biến tạm thời là không cần thiết. - Gishu
Vì vậy, một cái gì đó như thế này Questions.Get (Convert.ToInt16 (Question.Applications)) - jim
không cần phải chuyển đổi nó - chỉ cần truyền. - Michael Petrotta
Bạn có thể chỉ đơn giản là đúc theo một trong hai hướng; điều duy nhất để xem là enums không thực thi bất cứ điều gì (giá trị enum có thể là 288, mặc dù không có câu hỏi tồn tại với số đó) - Marc Gravell♦
@ Gishu Bạn có thể nói nó ... có vấn đề. ;) - Felix D.


Trên ghi chú có liên quan, nếu bạn muốn nhận int giá trị từ System.Enum, sau đó được e đây:

Enum e = Question.Role;

Bạn có thể dùng:

int i = Convert.ToInt32(e);
int i = (int)(object)e;
int i = (int)Enum.Parse(e.GetType(), e.ToString());
int i = (int)Enum.ToObject(e.GetType(), e);

Hai cái cuối cùng là xấu xí. Tôi thích cái đầu tiên.


55
2017-12-01 08:47





Nó dễ hơn bạn nghĩ - một enum đã là một int. Nó chỉ cần được nhắc nhở:

int y = (int)Question.Role;
Console.WriteLine(y); // prints 2

30
2018-06-03 06:51



Nitpick: điều này enum đã là một int. Các enums khác có thể là các kiểu khác nhau - hãy thử "enum SmallEnum: byte {A, B, C}" - mquander
Hoàn toàn đúng. Tham chiếu C #: "Mỗi kiểu liệt kê có một kiểu cơ bản, có thể là bất kỳ loại tích phân nào ngoại trừ char." - Michael Petrotta


Thí dụ:

Public Enum EmpNo
{
    Raj = 1
    Rahul,
    Priyanka
}

Và trong mã phía sau để có được giá trị enum:

int setempNo = (int)EmpNo.Raj; //This will give setempNo = 1

hoặc là

int setempNo = (int)EmpNo.Rahul; //This will give setempNo = 2

Enums sẽ tăng thêm 1 và bạn có thể đặt giá trị bắt đầu. Khác nó sẽ được gán là 0 ban đầu.


22
2017-09-25 10:43



Điều này thực sự biên dịch? - Peter Mortensen
Có thể cái gì đó là một Raj cũng được một Rahul hoặc một Priyanka? Xung đột giá trị của bạn và phải gấp đôi thành duy nhất, ví dụ: 0, 1, 2, 4, 8, v.v. Đây là mối quan tâm cốt lõi của tôi với enums. - Timothy Gonzalez
Tôi khá chắc chắn một hôn mê là mất tích sau Raj = 1và Public Enum nên là public enum - Rafalon


Gần đây tôi đã chuyển đổi từ việc sử dụng enums trong mã của tôi để thay thế bằng cách sử dụng các lớp với các hàm tạo được bảo vệ và các cá thể tĩnh được xác định trước (nhờ Roelof - C # Đảm bảo giá trị Enum hợp lệ - Phương pháp Futureproof).

Theo đó, dưới đây là cách tôi tiếp cận vấn đề này (bao gồm chuyển đổi ngầm đến / từ int).

public class Question
{
    // Attributes
    protected int index;
    protected string name;
    // Go with a dictionary to enforce unique index
    //protected static readonly ICollection<Question> values = new Collection<Question>();
    protected static readonly IDictionary<int,Question> values = new Dictionary<int,Question>();

    // Define the "enum" values
    public static readonly Question Role = new Question(2,"Role");
    public static readonly Question ProjectFunding = new Question(3, "Project Funding");
    public static readonly Question TotalEmployee = new Question(4, "Total Employee");
    public static readonly Question NumberOfServers = new Question(5, "Number of Servers");
    public static readonly Question TopBusinessConcern = new Question(6, "Top Business Concern");

    // Constructors
    protected Question(int index, string name)
    {
        this.index = index;
        this.name = name;
        values.Add(index, this);
    }

    // Easy int conversion
    public static implicit operator int(Question question) =>
        question.index; //nb: if question is null this will return a null pointer exception

    public static implicit operator Question(int index) =>        
        values.TryGetValue(index, out var question) ? question : null;

    // Easy string conversion (also update ToString for the same effect)
    public override string ToString() =>
        this.name;

    public static implicit operator string(Question question) =>
        question?.ToString();

    public static implicit operator Question(string name) =>
        name == null ? null : values.Values.FirstOrDefault(item => name.Equals(item.name, StringComparison.CurrentCultureIgnoreCase));


    // If you specifically want a Get(int x) function (though not required given the implicit converstion)
    public Question Get(int foo) =>
        foo; //(implicit conversion will take care of the conversion for you)
}

Ưu điểm của phương pháp này là bạn có được mọi thứ bạn sẽ có từ enum, nhưng mã của bạn bây giờ linh hoạt hơn nhiều, vì vậy bạn cần thực hiện các hành động khác nhau dựa trên giá trị của Question, bạn có thể đặt logic vào Question chính nó (tức là trong thời trang OO ưa thích) như trái ngược với việc đưa nhiều báo cáo trường hợp trong suốt mã của bạn để giải quyết từng kịch bản.


NB: Câu trả lời được cập nhật 2018-04-27 để sử dụng các tính năng C # 6; tức là các biểu thức khai báo và định nghĩa thân thể biểu thức lambda. Xem Lịch sử sửa đổi cho mã ban đầu. Điều này có lợi ích của việc đưa ra định nghĩa một chút ít tiết; đó là một trong những khiếu nại chính về cách tiếp cận của câu trả lời này.


18
2018-03-30 01:08



Tôi đoán đó là giao dịch giữa diễn viên rõ ràng và mã bạn phải viết để phá vỡ nó. Vẫn yêu thích việc thực hiện chỉ muốn nó không phải là quá dài. +1 - Lankymart
Tôi đã sử dụng một số loại khác nhau của các lớp học có cấu trúc tương tự như thế này. Tôi thấy họ làm việc kỳ diệu khi cố gắng làm theo phương pháp "đừng để tôi trở thành một thằng ngốc sau". - James Haug


Để đảm bảo một giá trị enum tồn tại và sau đó phân tích nó, bạn cũng có thể làm như sau.

// Fake Day of Week
string strDOWFake = "SuperDay";
// Real Day of Week
string strDOWReal = "Friday";
// Will hold which ever is the real DOW.
DayOfWeek enmDOW;

// See if fake DOW is defined in the DayOfWeek enumeration.
if (Enum.IsDefined(typeof(DayOfWeek), strDOWFake))
{
// This will never be reached since "SuperDay" 
// doesn't exist in the DayOfWeek enumeration.
    enmDOW = (DayOfWeek)Enum.Parse(typeof(DayOfWeek), strDOWFake);
}
// See if real DOW is defined in the DayOfWeek enumeration.
else if (Enum.IsDefined(typeof(DayOfWeek), strDOWReal))
{
    // This will parse the string into it's corresponding DOW enum object.
    enmDOW = (DayOfWeek)Enum.Parse(typeof(DayOfWeek), strDOWReal);
}

// Can now use the DOW enum object.
Console.Write("Today is " + enmDOW.ToString() + ".");

Tôi hi vọng cái này giúp được.


12
2017-07-22 20:56





Nếu bạn muốn lấy một số nguyên cho giá trị enum được lưu trữ trong một biến, kiểu đó sẽ là Question, để sử dụng ví dụ trong một phương pháp, bạn có thể chỉ cần làm điều này tôi đã viết trong ví dụ này:

enum Talen
{
    Engels = 1, Italiaans = 2, Portugees = 3, Nederlands = 4, Duits = 5, Dens = 6
}

Talen Geselecteerd;    

public void Form1()
{
    InitializeComponent()
    Geselecteerd = Talen.Nederlands;
}

// You can use the Enum type as a parameter, so any enumeration from any enumerator can be used as parameter
void VeranderenTitel(Enum e)
{
    this.Text = Convert.ToInt32(e).ToString();
}

Điều này sẽ thay đổi tiêu đề cửa sổ thành 4 vì biến Geselecteerd Là Talen.Nederlands. Nếu tôi đổi nó thành Talen.Portugees và gọi lại phương thức, văn bản sẽ thay đổi thành 3.

Tôi đã có một thời gian khó khăn tìm ra giải pháp đơn giản này trên internet và tôi không thể tìm thấy nó, vì vậy tôi đã thử nghiệm một cái gì đó và tìm thấy điều này. Hi vọng điêu nay co ich. ;)


12
2018-06-10 22:58





Một cách khác để làm điều đó:

Console.WriteLine("Name: {0}, Value: {0:D}", Question.Role);

Sẽ cho kết quả:

Name: Role, Value: 2

11
2017-09-19 05:42