Làm thế nào để cast int để enum?


3190

Làm thế nào có thể intđược chuyển thành một enumtrong C #?

Câu trả lời:


3792

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);

31
@FlySwat, điều gì xảy ra nếu YourEnumđộng và sẽ chỉ được biết khi chạy, và điều tôi muốn là chuyển đổi thành Enumgì?
Shimmy Weitzhandler

226
Xin lưu ý rằng Enum.Pude sẽ KHÔNG hoạt động nếu mã của bạn bị xáo trộn. Tại thời điểm chạy sau khi xáo trộn, chuỗi được so sánh với tên enum và tại thời điểm này, tên của enum không phải là tên mà bạn mong đợi. Kết quả phân tích của bạn sẽ thất bại khi kết quả là họ đã thành công trước đó.
jropella

158
THƯỞNG Nếu bạn sử dụng cú pháp "từ một chuỗi" ở trên và chuyển vào một chuỗi không hợp lệ là một số (ví dụ: "2342342" - giả sử đó không phải là giá trị của enum của bạn), nó thực sự sẽ cho phép mà không gây ra lỗi! Enum của bạn sẽ có giá trị đó (2342342) mặc dù đó không phải là một lựa chọn hợp lệ trong chính enum.
JoeCool

132
Tôi nghĩ rằng câu trả lời này là một chút ngày. Đối với chuỗi, bạn thực sự nên sử dụng ngay var result = Enum.TryParse(yourString, out yourEnum)hôm nay (và kiểm tra kết quả để xác định xem chuyển đổi có thất bại không).
Justin T Conroy

20
Cũng có Enum.Parsethể không phân biệt chữ hoa chữ thường bằng cách thêm truegiá trị tham số vào cuộc gọi:YourEnum foo = (YourEnum) Enum.Parse(typeof(YourEnum), yourString, true);
Erik Schierboom

900

Chỉ cần bỏ nó:

MyEnum e = (MyEnum)3;

Bạn có thể kiểm tra xem nó có trong phạm vi hay không bằng Enum.IsDefined :

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

218
Coi chừng 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à sự kết hợp của các cờ, ví dụ: Keys.L | Keys.Control
dtroy

15
Về Enum.IsDefined, hãy lưu ý rằng nó có thể nguy hiểm: msdn.microsoft.com/en-us/l Library / ms229025 (VS.90) .aspx
adrian

3
Tôi thích định nghĩa này: "Trả về một dấu hiệu cho biết một hằng số có giá trị được chỉ định có tồn tại trong một phép liệt kê cụ thể không" từ MSDN
Pap

3
... Bởi vì định nghĩa của bạn có thể gây hiểu nhầm, bởi vì bạn đang nói: "... hãy kiểm tra xem nó có nằm trong phạm vi không ..." ngụ ý trong một phạm vi số có giới hạn bắt đầu và kết thúc ...
Pap

3
@ mac9416 Tôi đã cố gắng đưa ra một ví dụ ngắn gọn tại gist.github.com/alowdon/f7354cda97bac70b44e1c04bc0991bcc - về cơ bản bằng cách sử dụng IsDefinedđể kiểm tra giá trị đầu vào, bạn sẽ dễ bị tổn thương khi thêm người IsDefinedmới giá trị tồn tại trong mã mới), nhưng có thể không hoạt động với mã gốc bạn đã viết. Do đó, an toàn hơn khi chỉ định rõ ràng các giá trị enum mà mã của bạn có thể xử lý.
adrian

238

Ngoài ra, sử dụng phương pháp 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>();

7
Để xử lý đầu vào của người dùng, có lẽ nên gọi là quá tải Enum.Pude cho phép bạn chỉ định rằng phép so sánh KHÔNG phân biệt chữ hoa chữ thường (nghĩa là người dùng gõ "đỏ" (chữ thường) sẽ làm hỏng mã trên mà không có thay đổi này .)
BrainSlugs83

9
Tiện dụng, nhưng câu hỏi đặc biệt hỏi về ints.
BJury

2
điều này cũng hoạt động nếu chuỗi là một số nguyên, ví dụ "2"
TruthOf42

2
Điều này sẽ đưa ra một ngoại lệ nếu enumString là null (có vấn đề tương tự ngày hôm qua). Cân nhắc sử dụng TryPude thay vì Parse. TryPude cũng sẽ kiểm tra xem T có phải là Loại Enum hay không
Justin

Kiểu phương thức mở rộng này System.Stringcó vẻ giống như ô nhiễm không gian tên
Mr Anderson

160

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

Công cụ hoạt động như thế nào

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 shortkiểu dữ liệu, có nghĩa là nó sẽ được lưu trữ trong bộ nhớ dưới dạng ngắn và sẽ hoạt động như một đoạn ngắn khi bạn sử dụng và sử dụng nó.

Nếu bạn nhìn nó 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 cần chú ý ở đây là cái 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ứ thứ gì bạn muốn trong một enum, miễn là các loại phù hợp .

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

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 enum, bộ thực thi chỉ phải thực hiện 2 điều: sao chép 4 byte và đặt tên cho nó là 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 loại giá trị - về cơ bản điều này 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 enum và số nguyên mà không cần sao chép dữ liệu.

Để đảm bảo an toàn, tôi nghĩ rằng đó là cách tốt nhất để biết rằng các loại cơ bản là giống nhau hoặc hoàn toàn có thể chuyển đổi 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 thức hoạt động, hãy thử đoạn 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 đúc để e2cũng hoạt động! Từ phối cảnh trình biên dịch ở trên, điều này có ý nghĩa: value__trường chỉ đơn giản chứa đầy 5 hoặc 6 và khi Console.WriteLinecác cuộc gọi ToString(), tên của e1được giải quyết trong khi tên của e2không.

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.

Cũng lưu ý rằng tôi rõ ràng về loại 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 phải bất ngờ nào trên đường. Để thấy những bất ngờ này đang hoạt động, bạn có thể sử dụng mã sau đây (thực tế 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();
}

7
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 trình độ kiến ​​thức này trong c #? Đây có phải là từ đọc qua đặc tả C #?
Rolan

20
@Rolan Đôi khi tôi ước nhiều người 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ứ nơi nào tôi có thể nhận được nó. Tôi đã đọ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í còn xem mã trình biên dịch x86 rất nhiều) và thực hiện rất nhiều thử nghiệm nhỏ. Ngoài ra, 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 được khoảng 30 năm và đến một lúc nào đó, một số thứ trở nên 'hợp lý' - f.ex. một enum nên tích hợp các loại, bởi vì nếu không interop sẽ bị hỏng (hoặc hiệu suất của bạn sẽ đi xuống cống).
đúng

9
Tôi tin rằng chìa khóa để làm kỹ thuật phần mềm đúng cách 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ó dịch như thế nào về f.ex. hoạt động của bộ xử lý và bộ nhớ tìm nạp / ghi. Nếu bạn hỏi làm thế nào để đạt đến mức đó, 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ỏ, khiến 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 đó (bao gồm cả dịch ngược, v.v.). Sau khi tìm ra tất cả các chi tiết và tất cả các đặc điểm, bạn có thể kiểm tra xem bạn đã hiểu đúng về tiêu chuẩn (buồn tẻ) chưa. Ít nhất, đó sẽ là cách tiếp cận của tôi.
đúng

1
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ó đưa ra một ngoại lệ khi chạy vì o là một đối tượng. Bạn có thể chuyển một biến int thành ngắn miễn là nó nằm trong phạm vi ngắn.
gravidThoughts

@gravidThoughts Cảm ơn. Trên thực tế, đây là một hoạt động unboxing, do đó, nó sẽ không thực hiện bất kỳ chuyển đổi ngầm nào như những gì bạn mô tả. Việc truyền tải đôi khi khó hiểu trong C # nếu bạn không biết chi tiết ... Dù sao đi nữa, bởi vì int! = short, Nó sẽ bị ném (việc bỏ hộp không thành công). Nếu bạn làm object o = (short)5;, nó sẽ hoạt động, bởi vì sau đó các loại sẽ phù hợp. Nó không phải là về phạm vi, nó thực sự về loại.
đúng


64

Tôi đang sử dụng đoạn mã này để truyền int cho enum của mình:

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

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


1
điều này là tốt tôi đã ngạc nhiên không có ngoại lệ khi truyền một giá trị không hợp lệ cho một enum được hỗ trợ.
orion elenzil

Điều này thực sự không quá khác biệt so với câu trả lời 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 truyền chuỗi thành loại Enum. Vì vậy, ngay cả khi chuỗi được truyền mà không có lỗi, Enum.IsDefined vẫn sẽ bắt được nó
Don Cheadle

53

Dưới đây là một lớp tiện ích tốt đẹp 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;
    }
}

47

Đố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;
    }
}

Không hoạt động cho cờ enum
Seyed Morteza Mousavi


35

Nếu bạn có một số nguyên hoạt động như một bitmask và có thể biểu thị một hoặc nhiều giá trị trong bảng liệt kê [Cờ], 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 = 0; flagIterator < 32; flagIterator++)
{
    // Determine the bit value (1,2,4,...,Int32.MinValue)
    int bitValue = 1 << flagIterator;

    // Check to see if the current flag exists in the bit mask
    if ((intValue & bitValue) != 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), bitValue))
            Console.WriteLine((MyEnum)bitValue);
    }
}

Lưu ý rằng điều này giả định rằng loại cơ bản của enumlà số nguyên 32 bit đã ký. Nếu đó là một loại số khác nhau, bạn phải thay đổi mã hóa cứng 32 để phản ánh các bit trong loại đó (hoặc lấy theo cách lập trình nó bằng cách sử dụng Enum.GetUnderlyingType())


1
Là vòng lặp này không bao giờ chấm dứt? flagIterator = 0x00000001, flagIterator = 0x00000002, flagIterator = 0x00000004, ..., flagIterator = 0x40000000, flagIterator = 0x80000000, flagIterator = 0x00000000. Nói cách khác, giá trị sẽ luôn thấp hơn 0x80000000 vì nó tràn về 0 sau trường hợp bit D31 = 1. Sau đó, nó vẫn là 0 mãi mãi vì dịch chuyển sang trái giá trị 0 cho 0
Christian Gingras

Bắt tuyệt vời @christiangingras, cảm ơn bạn! Tôi đã sửa đổi câu trả lời cho tài khoản đó và nó sẽ được tính đến khi bit cao nhất được đặt (tức là 0x80000000 / Int32.MinValue)
Evan M

27

Đôi khi bạn có một đối tượng để MyEnumloại. Giống

var MyEnumType = typeof(MyEnumType);

Sau đó:

Enum.ToObject(typeof(MyEnum), 3)

26

Đây là một cờ liệt kê phương thức chuyển đổi an toàn:

public static bool TryConvertToEnum<T>(this int instance, out T result)
  where T: Enum
{
  var enumType = typeof (T);
  var success = Enum.IsDefined(enumType, instance);
  if (success)
  {
    result = (T)Enum.ToObject(enumType, instance);
  }
  else
  {
    result = default(T);
  }
  return success;
}

3
Điều này hiện có thể được cải thiện với C # 7.3 bằng cách ràng buộc Enumthay vì struct, có nghĩa là chúng ta không phải dựa vào kiểm tra thời gian chạy!
Scott

20

nhập mô tả hình ảnh ở đây

Để chuyển đổi một chuỗi thành ENUM hoặc int thành hằng số ENUM, chúng ta cần sử dụng hàm Enum.Pude. Dưới đây là video youtube https://www.youtube.com/watch?v=4nhx4VwdRDk thực sự chứng minh bằng chuỗi và áp dụng tương tự cho int.

Mã đi như dưới đây trong đó "đỏ" là chuỗi và "MyColors" là ENUM màu có các hằng số màu.

MyColors EnumColors = (MyColors)Enum.Parse(typeof(MyColors), "Red");

20

Hơi xa khỏi câu hỏi ban đầu, nhưng tôi đã tìm thấy câu trả lời cho câu hỏi Stack Overflow Nhận giá trị int từ enum hữu ích. Tạo một lớp tĩnh với public const intcác thuộc tính, cho phép bạn dễ dàng thu thập một loạt các inthằng số liên quan và sau đó không phải intsử dụng chúng khi sử dụng chúng.

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

Rõ ràng, một số chức năng loại enum sẽ bị mất, nhưng để lưu trữ một loạt các hằng số id cơ sở dữ liệu, nó có vẻ như là một giải pháp khá gọn gàng.


5
enums thay thế việc sử dụng các hằng số nguyên như thế này vì chúng cung cấp nhiều loại an toàn hơn
Paul Richards

1
Paul, đây là một phương pháp thu thập các hằng số int liên quan (ví dụ: hằng số cơ sở dữ liệu id) để chúng có thể được sử dụng trực tiếp mà không cần phải chuyển chúng thành int mỗi khi chúng được sử dụng. Kiểu của họ số nguyên, ví dụ, DatabaseIdsEnum.
Ted

1
Có ít nhất một tình huống mà tôi đã tìm thấy trong đó an toàn loại enum có thể vô tình bị bỏ qua.
Thierry

Nhưng enums cũng đảm bảo các giá trị đều là duy nhất, một cách tiếp cận này cũng thiếu
derHugo

15

Điều này phân tích các số nguyên hoặc chuỗi thành một enum đích với khớp một phần trong dot.NET 4.0 bằng cách sử dụng các tổng quát như trong lớp tiện ích của Tawani ở trên. Tôi đang sử dụng nó để chuyển đổi các biến chuyển đổi dòng lệnh có thể không đầy đủ. Vì một enum không thể là null, nên bạn nên cung cấp một giá trị mặc định. Nó có thể được gọi như thế này:

var result = EnumParser<MyEnum>.Parse(valueToParse, MyEnum.FirstValue);

Đây là mã:

using System;

public class EnumParser<T> where T : struct
{
    public static T Parse(int toParse, T defaultVal)
    {
        return Parse(toParse + "", defaultVal);
    }
    public static T Parse(string toParse, T defaultVal) 
    {
        T enumVal = defaultVal;
        if (defaultVal is Enum && !String.IsNullOrEmpty(toParse))
        {
            int index;
            if (int.TryParse(toParse, out index))
            {
                Enum.TryParse(index + "", out enumVal);
            }
            else
            {
                if (!Enum.TryParse<T>(toParse + "", true, out enumVal))
                {
                    MatchPartialName(toParse, ref enumVal);
                }
            }
        }
        return enumVal;
    }

    public static void MatchPartialName(string toParse, ref T enumVal)
    {
        foreach (string member in enumVal.GetType().GetEnumNames())
        {
            if (member.ToLower().Contains(toParse.ToLower()))
            {
                if (Enum.TryParse<T>(member + "", out enumVal))
                {
                    break;
                }
            }
        }
    }
}

FYI: Câu hỏi là về số nguyên, không ai đề cập đến cũng sẽ chuyển đổi rõ ràng trong Enum.TryPude ()


13

Từ một chuỗi: (Enum.Pude đã hết hạn, hãy sử dụng Enum.TryPude)

enum Importance
{}

Importance importance;

if (Enum.TryParse(value, out importance))
{
}

4
Câu hỏi đặc biệt hỏi về số nguyên.
Bury

4
Will Yu lòng chỉnh sửa câu trả lời của bạn cho mọi người biết Enum.TryParse sẽ làm việc trên một chuỗi giá trị hoặc tên của enum (Tôi không thể cưỡng lại)
JeremyWeir

1
Jeremy, Weir làm việc về điều đó (cũng không thể cưỡng lại).
huysentbeanw

11

Sau đây là phương pháp mở rộng tốt hơn một chút

public static string ToEnumString<TEnum>(this int enumValue)
        {
            var enumString = enumValue.ToString();
            if (Enum.IsDefined(typeof(TEnum), enumValue))
            {
                enumString = ((TEnum) Enum.ToObject(typeof (TEnum), enumValue)).ToString();
            }
            return enumString;
        }

10

Trong trường hợp của tôi, tôi cần trả lại enum từ dịch vụ WCF. Tôi cũng cần một cái tên thân thiện, không chỉ là enum.ToString ().

Đây là lớp WCF của tôi.

[DataContract]
public class EnumMember
{
    [DataMember]
    public string Description { get; set; }

    [DataMember]
    public int Value { get; set; }

    public static List<EnumMember> ConvertToList<T>()
    {
        Type type = typeof(T);

        if (!type.IsEnum)
        {
            throw new ArgumentException("T must be of type enumeration.");
        }

        var members = new List<EnumMember>();

        foreach (string item in System.Enum.GetNames(type))
        {
            var enumType = System.Enum.Parse(type, item);

            members.Add(
                new EnumMember() { Description = enumType.GetDescriptionValue(), Value = ((IConvertible)enumType).ToInt32(null) });
        }

        return members;
    }
}

Đây là phương thức mở rộng lấy Mô tả từ Enum.

    public static string GetDescriptionValue<T>(this T source)
    {
        FieldInfo fileInfo = source.GetType().GetField(source.ToString());
        DescriptionAttribute[] attributes = (DescriptionAttribute[])fileInfo.GetCustomAttributes(typeof(DescriptionAttribute), false);            

        if (attributes != null && attributes.Length > 0)
        {
            return attributes[0].Description;
        }
        else
        {
            return source.ToString();
        }
    }

Thực hiện:

return EnumMember.ConvertToList<YourType>();

9

Tôi không biết nữa nơi tôi có được phần mở rộng enum này, nhưng đó là từ stackoverflow. Tôi xin lỗi về điều này! Nhưng tôi đã lấy cái này và sửa đổi nó cho enum với Cờ. Đối với enum với Cờ tôi đã làm điều này:

  public static class Enum<T> where T : struct
  {
     private static readonly IEnumerable<T> All = Enum.GetValues(typeof (T)).Cast<T>();
     private static readonly Dictionary<int, T> Values = All.ToDictionary(k => Convert.ToInt32(k));

     public static T? CastOrNull(int value)
     {
        T foundValue;
        if (Values.TryGetValue(value, out foundValue))
        {
           return foundValue;
        }

        // For enums with Flags-Attribut.
        try
        {
           bool isFlag = typeof(T).GetCustomAttributes(typeof(FlagsAttribute), false).Length > 0;
           if (isFlag)
           {
              int existingIntValue = 0;

              foreach (T t in Enum.GetValues(typeof(T)))
              {
                 if ((value & Convert.ToInt32(t)) > 0)
                 {
                    existingIntValue |= Convert.ToInt32(t);
                 }
              }
              if (existingIntValue == 0)
              {
                 return null;
              }

              return (T)(Enum.Parse(typeof(T), existingIntValue.ToString(), true));
           }
        }
        catch (Exception)
        {
           return null;
        }
        return null;
     }
  }

Thí dụ:

[Flags]
public enum PetType
{
  None = 0, Dog = 1, Cat = 2, Fish = 4, Bird = 8, Reptile = 16, Other = 32
};

integer values 
1=Dog;
13= Dog | Fish | Bird;
96= Other;
128= Null;

9

Bạn nên xây dựng trong một số loại thư giãn phù hợp để mạnh mẽ hơn.

public static T ToEnum<T>(dynamic value)
{
    if (value == null)
    {
        // default value of an enum is the object that corresponds to
        // the default value of its underlying type
        // https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/default-values-table
        value = Activator.CreateInstance(Enum.GetUnderlyingType(typeof(T)));
    }
    else if (value is string name)
    {
        return (T)Enum.Parse(typeof(T), name);
    }

    return (T)Enum.ToObject(typeof(T),
             Convert.ChangeType(value, Enum.GetUnderlyingType(typeof(T))));
}

Trường hợp thử nghiệm

[Flags]
public enum A : uint
{
    None  = 0, 
    X     = 1 < 0,
    Y     = 1 < 1
}

static void Main(string[] args)
{
    var value = EnumHelper.ToEnum<A>(7m);
    var x = value.HasFlag(A.X); // true
    var y = value.HasFlag(A.Y); // true

    var value2 = EnumHelper.ToEnum<A>("X");

    var value3 = EnumHelper.ToEnum<A>(null);

    Console.ReadKey();
}

Đây là một câu trả lời tốt đẹp. Thật là xấu hổ khi nó xuống trang hiện tại!
MikeBeaton

8

Các cách khác nhau để chuyển đến và đi Enum

enum orientation : byte
{
 north = 1,
 south = 2,
 east = 3,
 west = 4
}

class Program
{
  static void Main(string[] args)
  {
    orientation myDirection = orientation.north;
    Console.WriteLine(“myDirection = {0}”, myDirection); //output myDirection =north
    Console.WriteLine((byte)myDirection); //output 1

    string strDir = Convert.ToString(myDirection);
        Console.WriteLine(strDir); //output north

    string myString = north”; //to convert string to Enum
    myDirection = (orientation)Enum.Parse(typeof(orientation),myString);


 }
}

8

Nó có thể giúp bạn chuyển đổi bất kỳ dữ liệu đầu vào cho người sử dụng mong muốn enum . Giả sử bạn có một enum như bên dưới mà theo mặc định int . Vui lòng thêm một giá trị mặc định ở đầu enum của bạn. Được sử dụng tại trợ giúp medthod khi không tìm thấy kết quả khớp với giá trị đầu vào.

public enum FriendType  
{
    Default,
    Audio,
    Video,
    Image
}

public static class EnumHelper<T>
{
    public static T ConvertToEnum(dynamic value)
    {
        var result = default(T);
        var tempType = 0;

        //see Note below
        if (value != null &&
            int.TryParse(value.ToString(), out  tempType) && 
            Enum.IsDefined(typeof(T), tempType))
        {
            result = (T)Enum.ToObject(typeof(T), tempType); 
        }
        return result;
    }
}

NB: Ở đây tôi cố gắng phân tích giá trị thành int, vì enum theo mặc định int Nếu bạn định nghĩa enum như thế này là kiểu byte .

public enum MediaType : byte
{
    Default,
    Audio,
    Video,
    Image
} 

Bạn cần thay đổi phân tích cú pháp theo phương thức của trình trợ giúp từ

int.TryParse(value.ToString(), out  tempType)

đến

byte.TryParse(value.ToString(), out tempType)

Tôi kiểm tra phương pháp của mình để theo dõi đầu vào

EnumHelper<FriendType>.ConvertToEnum(null);
EnumHelper<FriendType>.ConvertToEnum("");
EnumHelper<FriendType>.ConvertToEnum("-1");
EnumHelper<FriendType>.ConvertToEnum("6");
EnumHelper<FriendType>.ConvertToEnum("");
EnumHelper<FriendType>.ConvertToEnum("2");
EnumHelper<FriendType>.ConvertToEnum(-1);
EnumHelper<FriendType>.ConvertToEnum(0);
EnumHelper<FriendType>.ConvertToEnum(1);
EnumHelper<FriendType>.ConvertToEnum(9);

xin lỗi vì tiếng Anh của tôi


8

Dưới đây là một phương pháp khuyến nông có phôi Int32để Enum.

Nó tôn vinh cờ bitwise ngay cả khi giá trị cao hơn mức tối đa có thể. Ví dụ: nếu bạn có một enum với các khả năng 1 , 24 , nhưng int là 9 , nó hiểu rằng là 1 khi không có 8 . Điều này cho phép bạn thực hiện cập nhật dữ liệu trước khi cập nhật mã.

   public static TEnum ToEnum<TEnum>(this int val) where TEnum : struct, IComparable, IFormattable, IConvertible
    {
        if (!typeof(TEnum).IsEnum)
        {
            return default(TEnum);
        }

        if (Enum.IsDefined(typeof(TEnum), val))
        {//if a straightforward single value, return that
            return (TEnum)Enum.ToObject(typeof(TEnum), val);
        }

        var candidates = Enum
            .GetValues(typeof(TEnum))
            .Cast<int>()
            .ToList();

        var isBitwise = candidates
            .Select((n, i) => {
                if (i < 2) return n == 0 || n == 1;
                return n / 2 == candidates[i - 1];
            })
            .All(y => y);

        var maxPossible = candidates.Sum();

        if (
            Enum.TryParse(val.ToString(), out TEnum asEnum)
            && (val <= maxPossible || !isBitwise)
        ){//if it can be parsed as a bitwise enum with multiple flags,
          //or is not bitwise, return the result of TryParse
            return asEnum;
        }

        //If the value is higher than all possible combinations,
        //remove the high imaginary values not accounted for in the enum
        var excess = Enumerable
            .Range(0, 32)
            .Select(n => (int)Math.Pow(2, n))
            .Where(n => n <= val && n > 0 && !candidates.Contains(n))
            .Sum();

        return Enum.TryParse((val - excess).ToString(), out asEnum) ? asEnum : default(TEnum);
    }

6

cách dễ dàng và rõ ràng để chuyển một int thành enum trong c #:

 public class Program
    {
        public enum Color : int
        {
            Blue = 0,
            Black = 1,
            Green = 2,
            Gray = 3,
            Yellow =4
        }

        public static void Main(string[] args)
        {
            //from string
            Console.WriteLine((Color) Enum.Parse(typeof(Color), "Green"));

            //from int
            Console.WriteLine((Color)2);

            //From number you can also
            Console.WriteLine((Color)Enum.ToObject(typeof(Color) ,2));
        }
    }

6

Bạn chỉ cần sử dụng chuyển đổi rõ ràng Cast int thành enum hoặc enum thành int

class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine((int)Number.three); //Output=3

        Console.WriteLine((Number)3);// Outout three
        Console.Read();
    }

    public enum Number
    {
        Zero = 0,
        One = 1,
        Two = 2,
        three = 3
    }
}

4
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;

namespace SamplePrograme
{
    public class Program
    {
        public enum Suit : int
        {
            Spades = 0,
            Hearts = 1,
            Clubs = 2,
            Diamonds = 3
        }

        public static void Main(string[] args)
        {
            //from string
            Console.WriteLine((Suit) Enum.Parse(typeof(Suit), "Clubs"));

            //from int
            Console.WriteLine((Suit)1);

            //From number you can also
            Console.WriteLine((Suit)Enum.ToObject(typeof(Suit) ,1));
        }
    }
}

3

Bạn chỉ cần làm như dưới đây:

int intToCast = 1;
TargetEnum f = (TargetEnum) intToCast ;

Để đảm bảo rằng bạn chỉ truyền đúng giá trị và bạn có thể ném ngoại lệ theo cách khác:

int intToCast = 1;
if (Enum.IsDefined(typeof(TargetEnum), intToCast ))
{
    TargetEnum target = (TargetEnum)intToCast ;
}
else
{
   // Throw your exception.
}

Lưu ý rằng việc sử dụng IsDefined là tốn kém và thậm chí còn hơn cả việc truyền, do đó tùy thuộc vào việc triển khai của bạn để quyết định sử dụng hay không.


3

Bạn có thể sử dụng phương pháp mở rộng.

public static class Extensions
{

    public static T ToEnum<T>(this string data) where T : struct
    {
        if (!Enum.TryParse(data, true, out T enumVariable))
        {
            if (Enum.IsDefined(typeof(T), enumVariable))
            {
                return enumVariable;
            }
        }

        return default;
    }

    public static T ToEnum<T>(this int data) where T : struct
    {
        return (T)Enum.ToObject(typeof(T), data);
    }
}

sử dụng như mã dưới đây

enum:

public enum DaysOfWeeks
{
    Monday = 1,
    Tuesday = 2,
    Wednesday = 3,
    Thursday = 4,
    Friday = 5,
    Saturday = 6,
    Sunday = 7,
}

Sử dụng :

 string Monday = "Mon";
 int Wednesday = 3;
 var Mon = Monday.ToEnum<DaysOfWeeks>();
 var Wed = Wednesday.ToEnum<DaysOfWeeks>();
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.