Câu hỏi Truyền int vào enum trong C #


Làm sao có thể int được đúc vào một enum trong C #?


2571
2017-08-27 03:58


gốc


Đối với vòng khác: get-int-value-from-enum - nawfal
Video 5 phút miễn phí bao gồm câu trả lời hay nhất bên dưới: app.deviq.com/courses/how-do-i-convert-int-to-enum-in-c-sharp - ssmith


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


Từ một chuỗi:

YourEnum foo = (YourEnum) Enum.Parse(typeof(YourEnum), yourString);
// the foo.ToString().Contains(",") check is necessary for enumerations marked with an [Flags] attribute
if (!Enum.IsDefined(typeof(YourEnum), foo) && !foo.ToString().Contains(","))
  throw new InvalidOperationException($"{yourString} is not an underlying value of the YourEnum enumeration.")

Từ một int:

YourEnum foo = (YourEnum)yourInt;

Cập nhật:

Từ số bạn cũng có thể

YourEnum foo = (YourEnum)Enum.ToObject(typeof(YourEnum) , yourInt);

3123
2017-08-27 03:59



@ FlySwat, nếu YourEnum năng động và sẽ chỉ được biết khi chạy, và những gì tôi muốn là chuyển đổi thành Enum? - Shimmy
Lưu ý rằng Enum.Parse sẽ KHÔNG hoạt động nếu mã của bạn bị làm mờ. Tại thời gian chạy sau khi obfuscation chuỗi được so sánh với tên enum, và tại thời điểm này tên của enums không phải là những gì bạn mong đợi họ được. Phân tích cú pháp của bạn sẽ thất bại khi họ đã thành công trước đó. - jropella
CHIA SẺ Nếu bạn sử dụng cú pháp "từ chuỗi" ở trên và chuyển vào chuỗi không hợp lệ, đó là số (ví dụ: "2342342" - giả sử đó không phải là giá trị của enum của bạn), nó sẽ thực sự cho phép mà không có lỗi! Enum của bạn sẽ có giá trị đó (2342342) mặc dù nó không phải là một sự lựa chọn hợp lệ trong enum chính nó. - JoeCool
Tôi nghĩ câu trả lời này có chút thời gian. Đối với chuỗi, bạn thực sự nên sử dụng var result = Enum.TryParse(yourString, out yourEnum) ngày nay (và kiểm tra kết quả để xác định xem chuyển đổi có thành công không). - Justin T Conroy
Nó cũng có thể có Enum.Parse phân biệt chữ hoa chữ thường bằng cách thêm true giá trị tham số cho cuộc gọi: YourEnum foo = (YourEnum) Enum.Parse(typeof(YourEnum), yourString, true); - Erik Schierboom


Chỉ cần bỏ nó:

MyEnum e = (MyEnum)3;

Bạn có thể kiểm tra xem nó có trong phạm vi sử dụng hay không Enum.IsDefined:

if (Enum.IsDefined(typeof(MyEnum), 3)) { ... }

721
2017-08-27 04:01



Cẩn thận bạn không thể sử dụng Enum.IsDefined nếu bạn sử dụng thuộc tính Flags và giá trị là một sự kết hợp của cờ ví dụ: Keys.L | Keys.Control - dtroy
Về Enum.IsDefined, hãy lưu ý rằng nó có thể nguy hiểm: msdn.microsoft.com/en-us/library/ms229025(VS.90).aspx - adrian
Mặt khác, nếu tôi xác thực đầu vào dựa trên enum thư viện cung cấp, trước khi gửi nó vào thư viện chính nó ... - Alexander
Tôi thích định nghĩa này: "Trả về một dấu hiệu cho thấy một hằng số với một giá trị được chỉ định tồn tại trong một liệt kê cụ thể" từ MSDN - Pap
... Bởi vì định nghĩa của bạn có thể gây hiểu lầm, bởi vì bạn đang nói: "... kiểm tra xem nó nằm trong phạm vi ..." ngụ ý trong phạm vi số có giới hạn bắt đầu và kết thúc ... - Pap


Ngoài ra, hãy sử dụng phương pháp tiện ích mở rộng thay vì một lớp lót:

public static T ToEnum<T>(this string enumString)
{
    return (T) Enum.Parse(typeof (T), enumString);
}

Sử dụng:

Color colorEnum = "Red".ToEnum<Color>();

HOẶC LÀ

string color = "Red";
var colorEnum = color.ToEnum<Color>();

198
2017-11-11 13:27



Để xử lý đầu vào của người dùng, có thể là một ý tưởng tốt để gọi quá tải của Enum.Parse cho phép bạn chỉ định rằng so sánh KHÔNG phân biệt chữ hoa chữ thường (tức là người dùng nhập "đỏ" (chữ thường) sẽ làm hỏng mã ở trên mà không cần thay đổi này .) - BrainSlugs83
Thật tuyệt, ngoại trừ việc đó không phải là câu hỏi. - nawfal
Tiện dụng, nhưng câu hỏi cụ thể hỏi về ints. - BJury
điều này cũng hoạt động nếu chuỗi là số nguyên, ví dụ: "2" - TruthOf42
Điều này sẽ ném một ngoại lệ nếu enumString là null (đã có một vấn đề tương tự ngày hôm qua). Cân nhắc sử dụng TryParse thay vì Parse. TryParse cũng sẽ kiểm tra xem T là một Loại Enum - Justin


Tôi nghĩ rằng để có được một câu trả lời hoàn chỉnh, mọi người phải biết làm thế nào enums làm việc trong nội bộ trong NET.

Cách hoạt động của nội dung

Một enum trong .NET là một cấu trúc ánh xạ một tập hợp các giá trị (các trường) thành một kiểu cơ bản (mặc định là int). Tuy nhiên, bạn thực sự có thể chọn loại tích phân mà enum của bạn ánh xạ tới:

public enum Foo : short

Trong trường hợp này enum được ánh xạ tới short loại dữ liệu, có nghĩa là nó sẽ được lưu trữ trong bộ nhớ như là một đoạn ngắn và sẽ hoạt động như một đoạn ngắn khi bạn cast và sử dụng nó.

Nếu bạn nhìn vào nó từ một quan điểm IL, một enum (bình thường, int) trông như thế này:

.class public auto ansi serializable sealed BarFlag extends System.Enum
{
    .custom instance void System.FlagsAttribute::.ctor()
    .custom instance void ComVisibleAttribute::.ctor(bool) = { bool(true) }

    .field public static literal valuetype BarFlag AllFlags = int32(0x3fff)
    .field public static literal valuetype BarFlag Foo1 = int32(1)
    .field public static literal valuetype BarFlag Foo2 = int32(0x2000)

    // and so on for all flags or enum values

    .field public specialname rtspecialname int32 value__
}

Điều bạn nên chú ý ở đây là value__ được lưu trữ riêng biệt với các giá trị enum. Trong trường hợp của enum Foo ở trên, loại value__ là int16. Điều này về cơ bản có nghĩa là bạn có thể lưu trữ bất cứ điều gì bạn muốn trong một enum, miễn là loại so khớp.

Tại thời điểm này tôi muốn chỉ ra rằng System.Enum là một loại giá trị, về cơ bản có nghĩa là BarFlag sẽ chiếm 4 byte trong bộ nhớ và Foo sẽ mất 2 - ví dụ kích thước của loại cơ bản (nó thực sự phức tạp hơn thế, nhưng này ...).

Câu trả lời

Vì vậy, nếu bạn có một số nguyên mà bạn muốn ánh xạ tới một enum, thời gian chạy chỉ phải làm 2 việc: sao chép 4 byte và đặt tên cho nó một cái gì đó khác (tên của enum). Sao chép là ẩn vì dữ liệu được lưu trữ dưới dạng giá trị - điều này về cơ bản có nghĩa là nếu bạn sử dụng mã không được quản lý, bạn có thể chỉ cần trao đổi enums và số nguyên mà không sao chép dữ liệu.

Để làm cho nó an toàn, tôi nghĩ đó là cách tốt nhất để biết rằng các loại cơ bản là giống nhau hoặc chuyển đổi hoàn toàn và để đảm bảo các giá trị enum tồn tại (chúng không được kiểm tra theo mặc định!).

Để xem cách hoạt động của tính năng này, hãy thử mã sau:

public enum MyEnum : int
{
    Foo = 1,
    Bar = 2,
    Mek = 5
}

static void Main(string[] args)
{
    var e1 = (MyEnum)5;
    var e2 = (MyEnum)6;

    Console.WriteLine("{0} {1}", e1, e2);
    Console.ReadLine();
}

Lưu ý rằng truyền tới e2 cũng hoạt động! Từ quan điểm biên dịch trên đây có ý nghĩa: value__ trường được điền đơn giản bằng 5 hoặc 6 và khi Console.WriteLine cuộc gọi ToString(), tên của e1 được giải quyết trong khi tên của e2 không phải là.

Nếu đó không phải là những gì bạn dự định, hãy sử dụng Enum.IsDefined(typeof(MyEnum), 6) để kiểm tra xem giá trị bạn đang truyền bản đồ đến một enum đã xác định chưa.

Cũng lưu ý rằng tôi rõ ràng về kiểu cơ bản của enum, mặc dù trình biên dịch thực sự kiểm tra điều này. Tôi đang làm điều này để đảm bảo tôi không gặp bất kỳ điều gì bất ngờ trên con đường. Để xem những điều bất ngờ này trong hành động, bạn có thể sử dụng đoạn mã sau (thực ra tôi đã thấy điều này xảy ra rất nhiều trong mã cơ sở dữ liệu):

public enum MyEnum : short
{
    Mek = 5
}

static void Main(string[] args)
{
    var e1 = (MyEnum)32769; // will not compile, out of bounds for a short

    object o = 5;
    var e2 = (MyEnum)o;     // will throw at runtime, because o is of type int

    Console.WriteLine("{0} {1}", e1, e2);
    Console.ReadLine();
}

116
2018-04-03 07:39



Tôi nhận ra đây là một bài viết cũ, nhưng làm thế nào để bạn đạt được mức độ kiến ​​thức này trong c #? Đây có phải là từ đọc thông qua các đặc điểm kỹ thuật C #? - Rolan
@ Đôi khi tôi muốn nhiều người hơn sẽ hỏi điều đó. :-) Thành thật mà nói tôi không thực sự biết; Tôi cố gắng hiểu cách mọi thứ hoạt động và nhận thông tin ở bất cứ đâu tôi có thể nhận được. Tôi đã đọc các tiêu chuẩn C #, nhưng tôi cũng thường xuyên dịch ngược mã với Reflector (tôi thậm chí nhìn vào mã lắp ráp x86 rất nhiều) và làm tấn thí nghiệm nhỏ. Ngoài ra, việc biết về các ngôn ngữ khác sẽ giúp trong trường hợp này; Tôi đã làm CS trong khoảng 30 năm nay, và tại một số điểm nào đó những thứ nhất định trở thành 'hợp lý' - f.ex. một loại enum nên tách rời, bởi vì nếu không interop sẽ phá vỡ (hoặc hiệu suất của bạn sẽ đi xuống cống). - atlaste
Tôi tin rằng chìa khóa để làm kĩ nghệ phần mềm đúng là biết cách thức hoạt động của công cụ. Đối với tôi, điều đó có nghĩa là nếu bạn viết một đoạn mã, bạn sẽ biết nó được dịch như thế nào đối với f.ex. hoạt động của bộ xử lý và tìm nạp / ghi bộ nhớ. Nếu bạn hỏi làm thế nào để đạt đến cấp độ đó, tôi khuyên bạn nên xây dựng một tấn các trường hợp thử nghiệm nhỏ, làm cho chúng khó khăn hơn khi bạn đi, cố gắng dự đoán kết quả mỗi lần, và kiểm tra chúng sau đó (incl. Decompilation, vv). Sau khi tìm ra tất cả các chi tiết và tất cả các đặc tính, bạn có thể kiểm tra xem bạn đã nhận được nó ngay trong tiêu chuẩn (ngu si đần độn) chưa. Ít nhất, đó sẽ là cách tiếp cận của tôi. - atlaste
Câu trả lời tuyệt vời, cảm ơn! Trong mẫu mã cuối cùng của bạn, nó ném một ngoại lệ vào thời gian chạy vì o là một đối tượng. Bạn có thể truyền một biến int thành một đoạn ngắn miễn là nó nằm trong phạm vi ngắn. - gravidThoughts
@gravidThoughts Cảm ơn. Trên thực tế nó là một hoạt động unboxing, do đó, nó sẽ không làm bất kỳ chuyển đổi tiềm ẩn như những người bạn mô tả. Việc đúc đôi khi gây nhầm lẫn trong C # nếu bạn không biết chi tiết ... Nhưng dù sao, bởi vì int ! = short, nó sẽ ném (unboxing thất bại). Nếu bạn làm object o = (short)5;, nó sẽ làm việc, bởi vì sau đó các loại sẽ phù hợp. Nó không phải về phạm vi, nó thực sự là về loại. - atlaste


Lấy ví dụ sau:

int one = 1;
MyEnum e = (MyEnum)one;

89
2017-08-27 04:00





Tôi đang sử dụng đoạn mã này để đúc int vào enum của tôi:

if (typeof(YourEnum).IsEnumDefined(valueToCast)) return (YourEnum)valueToCast;
else { //handle it here, if its not defined }

Tôi tìm thấy nó là giải pháp tốt nhất.


54
2017-10-21 10:05



Không hoạt động với cờ enums - Daniel Fisher lennybacon
điều này là tốt. tôi đã rất ngạc nhiên khi không có một ngoại lệ khi truyền một giá trị không hợp lệ đến một enum được sao lưu int. - orion elenzil
Điều này thực sự không khác biệt so với câu trả lời được đánh giá hàng đầu. Câu trả lời đó cũng thảo luận về việc sử dụng Enum.IsDefined sau khi bạn đã đưa chuỗi đó vào kiểu Enum. Vì vậy, ngay cả khi chuỗi được đúc mà không có lỗi, Enum.IsDefined sẽ vẫn bắt được nó - mmcrae


Dưới đây là một lớp tiện ích tốt cho Enums

public static class EnumHelper
{
    public static int[] ToIntArray<T>(T[] value)
    {
        int[] result = new int[value.Length];
        for (int i = 0; i < value.Length; i++)
            result[i] = Convert.ToInt32(value[i]);
        return result;
    }

    public static T[] FromIntArray<T>(int[] value) 
    {
        T[] result = new T[value.Length];
        for (int i = 0; i < value.Length; i++)
            result[i] = (T)Enum.ToObject(typeof(T),value[i]);
        return result;
    }


    internal static T Parse<T>(string value, T defaultValue)
    {
        if (Enum.IsDefined(typeof(T), value))
            return (T) Enum.Parse(typeof (T), value);

        int num;
        if(int.TryParse(value,out num))
        {
            if (Enum.IsDefined(typeof(T), num))
                return (T)Enum.ToObject(typeof(T), num);
        }

        return defaultValue;
    }
}

44
2017-09-07 04:42





Nếu bạn đã sẵn sàng cho phiên bản 4.0 .MẠNG LƯỚI Framework, có một cái mới Enum.TryParse () chức năng này rất hữu ích và hoạt động tốt với thuộc tính [Flags]. Xem Phương thức Enum.TryParse (String, TEnum%)


37
2017-11-01 14:58



Đó là hữu ích khi chuyển đổi từ một chuỗi. Nhưng không phải khi chuyển đổi từ một int. - CodesInChaos


Đối với các giá trị số, điều này an toàn hơn vì nó sẽ trả về một đối tượng bất kể là gì:

public static class EnumEx
{
    static public bool TryConvert<T>(int value, out T result)
    {
        result = default(T);
        bool success = Enum.IsDefined(typeof(T), value);
        if (success)
        {
            result = (T)Enum.ToObject(typeof(T), value);
        }
        return success;
    }
}

37
2018-02-21 15:22



Điều này không hoạt động với cờ enums - Daniel Fisher lennybacon


Nếu bạn có một số nguyên hoạt động như một bitmap và có thể đại diện cho một hoặc nhiều giá trị trong một liệt kê [Flags], bạn có thể sử dụng mã này để phân tích các giá trị cờ riêng lẻ thành một danh sách:

for (var flagIterator = 0x1; flagIterator <= 0x80000000; flagIterator <<= 1)
{
    // Check to see if the current flag exists in the bit mask
    if ((intValue & flagIterator) != 0)
    {
        // If the current flag exists in the enumeration, then we can add that value to the list
        // if the enumeration has that flag defined
        if (Enum.IsDefined(typeof(MyEnum), flagIterator))
            ListOfEnumValues.Add((MyEnum)flagIterator);
    }
}

25
2018-04-13 20:13





Đôi khi bạn có một đối tượng MyEnum kiểu. Như

var MyEnumType = typeof(MyEnumType);

Sau đó:

Enum.ToObject(typeof(MyEnum), 3)

22
2017-07-02 14:41