Làm thế nào để liệt kê một enum


3767

Làm thế nào bạn có thể liệt kê một enumtrong C #?

Ví dụ: đoạn mã sau không biên dịch:

public enum Suit
{
    Spades,
    Hearts,
    Clubs,
    Diamonds
}

public void EnumerateAllSuitsDemoMethod()
{
    foreach (Suit suit in Suit)
    {
        DoSomething(suit);
    }
}

Và nó đưa ra lỗi thời gian biên dịch sau:

'Suit' là 'loại' nhưng được sử dụng như 'biến'

Nó thất bại về Suittừ khóa, cái thứ hai.



2
Bạn có thể muốn kiểm tra nội dung của C # enums , thảo luận về vấn đề này cũng như các mẩu tin enum hữu ích khác
ChaseMedallion

Câu trả lời:


4613
foreach (Suit suit in (Suit[]) Enum.GetValues(typeof(Suit)))
{
}

Lưu ý : Việc truyền vào (Suit[])không thực sự cần thiết, nhưng nó làm cho mã 0,5 ns nhanh hơn .


97
Điều này không hoạt động nếu bạn có các giá trị trùng lặp trong danh sách điều tra viên.
Jessy

10
Tôi chỉ muốn chỉ ra rằng điều này, thật không may sẽ không hoạt động trong ánh sáng bạc, vì thư viện Silverlight không bao gồm enum.GetValues. Bạn phải sử dụng sự phản chiếu trong trường hợp này.
Giacomo Tagliabue

146
@Jessy này không hoạt động trong trường hợp trùng lặp như thế nào enum E {A = 0, B = 0}. Enum.GetValueskết quả là hai giá trị được trả về, mặc dù chúng giống nhau. E.A == E.Blà đúng, vì vậy không có sự phân biệt. Nếu bạn muốn tên riêng lẻ, thì bạn nên tìm kiếm Enum.GetNames.
nawfal

13
Sau đó, nếu bạn có các bản sao / từ đồng nghĩa trong enum của mình và bạn muốn có hành vi khác, bạn có thể sử dụng Distincttiện ích mở rộng của Linq (kể từ .NET 3.5), vì vậy foreach (var suit in ((Suit[])Enum.GetValues(typeof(Suit))).Distinct()) { }.
Jeppe Stig Nielsen

42
Tôi đã phạm sai lầm khi cố gắng sử dụng varcho các loại. Trình biên dịch sẽ làm cho biến một Objectthay vì enum. Liệt kê loại enum một cách rõ ràng.
jpmc26

695

Có vẻ như tôi thực sự muốn in ra tên của từng enum, hơn là các giá trị. Trong trường hợp đó Enum.GetNames()dường như là cách tiếp cận đúng.

public enum Suits
{
    Spades,
    Hearts,
    Clubs,
    Diamonds,
    NumSuits
}

public void PrintAllSuits()
{
    foreach (string name in Enum.GetNames(typeof(Suits)))
    {
        System.Console.WriteLine(name);
    }
}

Nhân tiện, tăng giá trị không phải là một cách tốt để liệt kê các giá trị của một enum. Bạn nên làm điều này thay vào đó.

Tôi sẽ sử dụng Enum.GetValues(typeof(Suit))thay thế.

public enum Suits
{
    Spades,
    Hearts,
    Clubs,
    Diamonds,
    NumSuits
}

public void PrintAllSuits()
{
    foreach (var suit in Enum.GetValues(typeof(Suits)))
    {
        System.Console.WriteLine(suit.ToString());
    }
}

2
Cú pháp VB tại đây: link
AndruWitta

Tôi lấy phiên bản của bạn với một số thay đổi nhỏ từ phía tôi : Enum.GetValues(typeof(Suits)).OfType<Suits>().ToArray(). Trong trường hợp đó tôi có thể lặp lại mảng các Suitsmục enum, không phải chuỗi.
Barabas

@Barabas tại sao không làm Suits suit in Enum.GetValues(typeof(Suits))?
dõi

@themadking ơi! Tất nhiên, sử dụng loại chính xác trông tốt hơn so với đoạn mã ... quái dị này !
Barabas

337

Tôi đã thực hiện một số phần mở rộng để sử dụng enum dễ dàng. Có lẽ ai đó có thể sử dụng nó ...

public static class EnumExtensions
{
    /// <summary>
    /// Gets all items for an enum value.
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="value">The value.</param>
    /// <returns></returns>
    public static IEnumerable<T> GetAllItems<T>(this Enum value)
    {
        foreach (object item in Enum.GetValues(typeof(T)))
        {
            yield return (T)item;
        }
    }

    /// <summary>
    /// Gets all items for an enum type.
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="value">The value.</param>
    /// <returns></returns>
    public static IEnumerable<T> GetAllItems<T>() where T : struct
    {
        foreach (object item in Enum.GetValues(typeof(T)))
        {
            yield return (T)item;
        }
    }

    /// <summary>
    /// Gets all combined items from an enum value.
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="value">The value.</param>
    /// <returns></returns>
    /// <example>
    /// Displays ValueA and ValueB.
    /// <code>
    /// EnumExample dummy = EnumExample.Combi;
    /// foreach (var item in dummy.GetAllSelectedItems<EnumExample>())
    /// {
    ///    Console.WriteLine(item);
    /// }
    /// </code>
    /// </example>
    public static IEnumerable<T> GetAllSelectedItems<T>(this Enum value)
    {
        int valueAsInt = Convert.ToInt32(value, CultureInfo.InvariantCulture);

        foreach (object item in Enum.GetValues(typeof(T)))
        {
            int itemAsInt = Convert.ToInt32(item, CultureInfo.InvariantCulture);

            if (itemAsInt == (valueAsInt & itemAsInt))
            {
                yield return (T)item;
            }
        }
    }

    /// <summary>
    /// Determines whether the enum value contains a specific value.
    /// </summary>
    /// <param name="value">The value.</param>
    /// <param name="request">The request.</param>
    /// <returns>
    ///     <c>true</c> if value contains the specified value; otherwise, <c>false</c>.
    /// </returns>
    /// <example>
    /// <code>
    /// EnumExample dummy = EnumExample.Combi;
    /// if (dummy.Contains<EnumExample>(EnumExample.ValueA))
    /// {
    ///     Console.WriteLine("dummy contains EnumExample.ValueA");
    /// }
    /// </code>
    /// </example>
    public static bool Contains<T>(this Enum value, T request)
    {
        int valueAsInt = Convert.ToInt32(value, CultureInfo.InvariantCulture);
        int requestAsInt = Convert.ToInt32(request, CultureInfo.InvariantCulture);

        if (requestAsInt == (valueAsInt & requestAsInt))
        {
            return true;
        }

        return false;
    }
}

Bản thân enum phải được trang trí với FlagsAttribution :

[Flags]
public enum EnumExample
{
    ValueA = 1,
    ValueB = 2,
    ValueC = 4,
    ValueD = 8,
    Combi = ValueA | ValueB
}

13
Một lớp lót cho phương pháp mở rộng đầu tiên; nó không còn lười biếng nữa trả về Enum.GetValues ​​(typeof (T)). Cast <T> ();
Leyu

2
Ngoài ra, bạn cũng có thể sử dụng OfType: Enum.GetValues ​​(typeof (T)). OfType <T> (). Thật tệ khi không có phiên bản chung của GetValues ​​<T> () thì nó sẽ còn hấp dẫn hơn nữa.
jpierson

3
Có lẽ ai đó có thể chỉ cho bạn cách sử dụng các tiện ích mở rộng này? Trình biên dịch không hiển thị các phương thức mở rộng trên enum EnumExample.
Tomas

1
bất cứ ai có thể thêm ví dụ làm thế nào để sử dụng các chức năng?
Vermwini Verma

3
+1 cho mã có thể sử dụng lại: ví dụ - lưu các phương thức mở rộng này trong thư viện và tham chiếu nó [Cờ] công khai enum mytypes {name1, name2}; Liệt kê <string> myTypeNames = mytypes.Get ALLItems ();
Krishna

178

Một số phiên bản của .NET framework không hỗ trợ Enum.GetValues. Đây là một cách giải quyết tốt từ Ý tưởng 2.0: Enum.GetValues ​​trong Compact Framework :

public Enum[] GetValues(Enum enumeration)
{
    FieldInfo[] fields = enumeration.GetType().GetFields(BindingFlags.Static | BindingFlags.Public);
    Enum[] enumerations = new Enum[fields.Length];

    for (var i = 0; i < fields.Length; i++)
        enumerations[i] = (Enum) fields[i].GetValue(enumeration);

    return enumerations;
}

Như với bất kỳ mã nào liên quan đến sự phản chiếu , bạn nên thực hiện các bước để đảm bảo nó chỉ chạy một lần và kết quả được lưu trữ.


18
Tại sao không sử dụng từ khóa suất ở đây thay vì khởi tạo một danh sách?
Eric Mickelsen

1
hoặc ngắn hơn:return type.GetFields().Where(x => x.IsLiteral).Select(x => x.GetValue(null)).Cast<Enum>();
nawfal

7
@nawfal: Linq không khả dụng .Net CF 2.0.
Gabriel GM

@Ekevoo Làm cách nào để liên kết các giá trị enum này với DropDownList trong MVC?
Jack

115

Sử dụng Cast<T>:

var suits = Enum.GetValues(typeof(Suit)).Cast<Suit>();

Có bạn đi , IEnumerable<Suit>.


1
Điều này cũng hoạt động trong frommệnh đề và foreachkhai báo tiêu đề.
Aluan Haddad

97

Tôi nghĩ rằng điều này hiệu quả hơn các đề xuất khác vì GetValues()không được gọi mỗi khi bạn có một vòng lặp. Nó cũng súc tích hơn. Và bạn gặp lỗi thời gian biên dịch, không phải là ngoại lệ thời gian chạy nếu Suitkhông phải là enum.

EnumLoop<Suit>.ForEach((suit) => {
    DoSomethingWith(suit);
});

EnumLoop có định nghĩa hoàn toàn chung chung này:

class EnumLoop<Key> where Key : struct, IConvertible {
    static readonly Key[] arr = (Key[])Enum.GetValues(typeof(Key));
    static internal void ForEach(Action<Key> act) {
        for (int i = 0; i < arr.Length; i++) {
            act(arr[i]);
        }
    }
}

6
Cẩn thận với việc sử dụng thuốc generic như thế này. Nếu bạn cố gắng sử dụng EnumLoopvới một số loại không phải là enum, nó sẽ biên dịch tốt, nhưng ném một ngoại lệ khi chạy.
Svick

7
Cảm ơn bạn. Các ngoại lệ thời gian chạy sẽ thực sự xảy ra với các câu trả lời khác trên trang này ... ngoại trừ câu trả lời này vì tôi đã thêm "where Key: struct, IConvertible" để bạn gặp lỗi thời gian biên dịch trong hầu hết các trường hợp.
James

3
Không, GetValues ​​() chỉ được gọi một lần trong foreach.
Alex Blokha

4
James, tôi sẽ không khuyến khích lớp học của bạn bởi vì thông minh là tốt để viết nhưng trong mã sản xuất mà nhiều người sẽ duy trì và cập nhật, thông minh là công việc phụ. Nếu nó tạo ra một khoản tiết kiệm lớn hoặc sẽ được sử dụng rất nhiều - vì vậy khoản tiết kiệm rất lớn và mọi người sẽ trở nên quen thuộc với nó - nó đáng giá, nhưng trong hầu hết các trường hợp, nó làm chậm mọi người cố gắng đọc và cập nhật mã và giới thiệu khả năng lỗi nguồn trong tương lai. Ít mã hơn là tốt hơn :) ít phức tạp hơn thậm chí còn tốt hơn.
Cấp M

2
@GrantM Tại sao? Mã này không phức tạp và nó cực kỳ ngắn. Trên hết, việc viết lớp một lần sẽ cho phép các lần lặp mã ngắn hơn với việc sử dụng là theo ví dụ của anh ấy. Điều này cực kỳ sạch sẽ, nếu bạn không thể cập nhật mã đó, có lẽ bạn không thể cập nhật bất kỳ mã nào của công ty.
Dispersia

77

Bạn sẽ không nhận được Enum.GetValues()trong Silverlight .

Bài viết gốc của Einar Ingebrigtsen :

public class EnumHelper
{
    public static T[] GetValues<T>()
    {
        Type enumType = typeof(T);

        if (!enumType.IsEnum)
        {
            throw new ArgumentException("Type '" + enumType.Name + "' is not an enum");
        }

        List<T> values = new List<T>();

        var fields = from field in enumType.GetFields()
                     where field.IsLiteral
                     select field;

        foreach (FieldInfo field in fields)
        {
            object value = field.GetValue(enumType);
            values.Add((T)value);
        }

        return values.ToArray();
    }

    public static object[] GetValues(Type enumType)
    {
        if (!enumType.IsEnum)
        {
            throw new ArgumentException("Type '" + enumType.Name + "' is not an enum");
        }

        List<object> values = new List<object>();

        var fields = from field in enumType.GetFields()
                     where field.IsLiteral
                     select field;

        foreach (FieldInfo field in fields)
        {
            object value = field.GetValue(enumType);
            values.Add(value);
        }

        return values.ToArray();
    }
}

2
Giải pháp tốt đẹp, nhưng một số tái cấu trúc sẽ tốt hơn! :)
nawfal

Tôi đang sử dụng .NET framework 4.0 & silverlight enum.getvalues ​​hoạt động, mã tôi đã sử dụng là ---> enum.GetValues ​​(typeof (enum))
Ananda

2
Bắt đầu với C # 7.3 (Visual Studio 2017 v15.7), người ta có thể sử dụngwhere T: Enum
Yahoo Serious

59

Giải pháp của tôi hoạt động trong .NET Compact Framework (3.5) và hỗ trợ kiểm tra kiểu tại thời gian biên dịch :

public static List<T> GetEnumValues<T>() where T : new() {
    T valueType = new T();
    return typeof(T).GetFields()
        .Select(fieldInfo => (T)fieldInfo.GetValue(valueType))
        .Distinct()
        .ToList();
}

public static List<String> GetEnumNames<T>() {
    return typeof (T).GetFields()
        .Select(info => info.Name)
        .Distinct()
        .ToList();
}
  • Nếu bất cứ ai biết cách thoát khỏi T valueType = new T(), tôi rất vui khi thấy một giải pháp.

Một cuộc gọi sẽ như thế này:

List<MyEnum> result = Utils.GetEnumValues<MyEnum>();

2
Còn việc sử dụng T valueType = default(T)thì sao?
Oliver

Thật tuyệt, tôi thậm chí còn không biết từ khóa đó. Luôn luôn tốt đẹp để học một cái gì đó mới. Cảm ơn bạn! Có phải nó luôn trả về một tham chiếu đến cùng một đối tượng hoặc nó tạo một thể hiện mới mỗi khi câu lệnh mặc định được gọi? Tôi đã không tìm thấy bất cứ điều gì trên mạng về điều này cho đến nay, nhưng nếu nó tạo ra một trường hợp mới mỗi lần, nó sẽ đánh bại mục đích mà tôi đang tìm kiếm (có một lớp lót ^^).
Mallox

1
Điều này sẽ không tạo ra một ví dụ mới cho mỗi lần lặp qua bảng liệt kê chứ?
Mallox

1
-1 cho "hỗ trợ kiểm tra kiểu tại thời gian biên dịch:". Kiểm tra loại nào? Điều này sẽ làm việc cho bất kỳ new() T. Ngoài ra, bạn không cần new T()gì cả, bạn chỉ có thể chọn các trường tĩnh và làm .GetValue(null). Xem câu trả lời của Aubrey.
nawfal

2
Bắt đầu với C # 7.3 (Visual Studio 2017 v15.7), người ta có thể sử dụngwhere T: Enum
Yahoo Serious

52

Tôi nghĩ bạn có thể sử dụng

Enum.GetNames(Suit)

6
Enum.GetValues ​​(Bộ quần áo)
Ian Boyd

50
public void PrintAllSuits()
{
    foreach(string suit in Enum.GetNames(typeof(Suits)))
    {
        Console.WriteLine(suit);
    }
}

2
Điều đó liệt kê một chuỗi, đừng quên chuyển đổi những thứ đó thành giá trị liệt kê để liệt kê có thể được liệt kê.
Ian Boyd

1
Tôi thấy từ bản chỉnh sửa của bạn rằng bạn muốn thực sự hoạt động trên enum, đoạn mã trên đã giải quyết bài viết gốc của bạn.
Joshua Drake

49
foreach (Suit suit in Enum.GetValues(typeof(Suit))) { }

Tôi đã nghe những tin đồn mơ hồ rằng điều này rất chậm. Có ai biết không? - Orion Edwards ngày 15 tháng 10 năm 08 lúc 1:31 7

Tôi nghĩ rằng bộ nhớ đệm mảng sẽ tăng tốc đáng kể. Dường như bạn đang nhận được một mảng mới (thông qua sự phản chiếu) mỗi lần. Hơn:

Array enums = Enum.GetValues(typeof(Suit));
foreach (Suit suitEnum in enums) 
{
    DoSomething(suitEnum);
}

Đó là nhanh hơn một chút, ja?


5
Trình biên dịch nên chăm sóc điều này, mặc dù.
Stephan bijzitter 23/2/2015

@StephanBijzitter Wow, bạn đang đọc khá xa về điều này :-) Tôi đồng ý, trình biên dịch sẽ làm cho giải pháp của tôi không cần thiết.
Chuộc tội có giới hạn

1
Điều này là không cần thiết. Nhìn vào mã được biên dịch trong ILSpy, trình biên dịch chắc chắn đã làm điều này. Tại sao câu trả lời này được nâng cấp ở tất cả, ít hơn 35 lần?
mhenry1384

1
Nó đã được nâng cấp từ lâu. Một thời gian rất dài trước đây. Mặc dù vậy, tôi cũng muốn rằng trình biên dịch cũng đã giải quyết điều này. Nhưng nó chắc chắn trông hiệu quả hơn, phải không? ;-)
Chuộc tội có giới hạn

32

Ba cách:

  1. Enum.GetValues(type) // Kể từ .NET 1.1, không có trong Silverlight hoặc .NET Compact Framework
  2. type.GetEnumValues() // Chỉ trên .NET 4 trở lên
  3. type.GetFields().Where(x => x.IsLiteral).Select(x => x.GetValue(null)) // Hoạt động ở mọi nơi

Tôi không chắc tại sao GetEnumValuesđược giới thiệu trên các trường hợp loại. Nó không phải là rất dễ đọc đối với tôi.


Có một lớp người trợ giúp như thế Enum<T>là điều dễ đọc và đáng nhớ nhất đối với tôi:

public static class Enum<T> where T : struct, IComparable, IFormattable, IConvertible
{
    public static IEnumerable<T> GetValues()
    {
        return (T[])Enum.GetValues(typeof(T));
    }

    public static IEnumerable<string> GetNames()
    {
        return Enum.GetNames(typeof(T));
    }
}

Bây giờ bạn gọi:

Enum<Suit>.GetValues();

// Or
Enum.GetValues(typeof(Suit)); // Pretty consistent style

Người ta cũng có thể sử dụng một số loại bộ nhớ đệm nếu hiệu suất có vấn đề, nhưng tôi không hy vọng đây sẽ là một vấn đề.

public static class Enum<T> where T : struct, IComparable, IFormattable, IConvertible
{
    // Lazily loaded
    static T[] values;
    static string[] names;

    public static IEnumerable<T> GetValues()
    {
        return values ?? (values = (T[])Enum.GetValues(typeof(T)));
    }

    public static IEnumerable<string> GetNames()
    {
        return names ?? (names = Enum.GetNames(typeof(T)));
    }
}

Đây là một bản tóm tắt tốt đẹp của phương pháp. Tôi nghĩ rằng bạn nên hợp nhất câu trả lời khác của bạn vào điều này mặc dù. Sự thật là enum rất đặc biệt và việc lặp qua chúng thường (thường) có giá trị như liệt kê vì bạn biết rằng các giá trị sẽ không bao giờ thay đổi. IOW, Nếu bạn có một enum luôn thay đổi thì bạn đã chọn cấu trúc dữ liệu sai để bắt đầu.
krowe2

31

Chỉ bằng cách kết hợp các câu trả lời hàng đầu, tôi đã tạo ra một phần mở rộng rất đơn giản:

public static class EnumExtensions
{
    /// <summary>
    /// Gets all items for an enum value.
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="value">The value.</param>
    /// <returns></returns>
    public static IEnumerable<T> GetAllItems<T>(this T value) where T : Enum
    {
        return (T[])Enum.GetValues(typeof (T));
    }
}

Nó sạch sẽ, đơn giản và, bởi nhận xét của @ Jeppe-Stig-Nielsen, nhanh chóng.


6
Bắt đầu với C # 7.3 (Visual Studio 2017 v15.7), người ta có thể sử dụngwhere T: Enum
Yahoo Serious

24

Có hai cách để lặp lại một Enum:

1. var values =  Enum.GetValues(typeof(myenum))
2. var values =  Enum.GetNames(typeof(myenum))

Cái đầu tiên sẽ cung cấp cho bạn các giá trị dưới dạng trên một mảng ** object** s và thứ hai sẽ cung cấp cho bạn các giá trị dưới dạng một mảng ** String** s.

Sử dụng nó trong một foreachvòng lặp như dưới đây:

foreach(var value in values)
{
    // Do operations here
}

2
Có lẽ vì điều này đã được đề cập trong nhiều câu trả lời? Chúng ta đừng làm cho câu trả lời dư thừa.
nawfal

@nawfal có thể được đề cập trong các câu trả lời khác, mặc dù không được kết luận tốt trong hầu hết các câu trả lời.
Kylo Ren

23

Tôi sử dụng ToString () sau đó phân tách và phân tích mảng nhổ trong cờ.

[Flags]
public enum ABC {
   a = 1,
   b = 2,
   c = 4
};

public IEnumerable<ABC> Getselected (ABC flags)
{
   var values = flags.ToString().Split(',');
   var enums = values.Select(x => (ABC)Enum.Parse(typeof(ABC), x.Trim()));
   return enums;
}

ABC temp= ABC.a | ABC.b;
var list = getSelected (temp);
foreach (var item in list)
{
   Console.WriteLine(item.ToString() + " ID=" + (int)item);
}

17

Tôi không giữ quan điểm này là tốt hơn, hoặc thậm chí là tốt. Tôi chỉ nêu một giải pháp khác.

Nếu giá trị enum nằm trong phạm vi từ 0 đến n - 1, thì một thay thế chung là:

public void EnumerateEnum<T>()
{
    int length = Enum.GetValues(typeof(T)).Length;
    for (var i = 0; i < length; i++)
    {
        var @enum = (T)(object)i;
    }
}

Nếu các giá trị enum tiếp giáp nhau và bạn có thể cung cấp phần tử đầu tiên và cuối cùng của enum, thì:

public void EnumerateEnum()
{
    for (var i = Suit.Spade; i <= Suit.Diamond; i++)
    {
        var @enum = i;
    }
}

Nhưng đó không phải là liệt kê nghiêm ngặt, chỉ cần lặp đi lặp lại. Phương pháp thứ hai nhanh hơn nhiều so với bất kỳ phương pháp nào khác mặc dù ...


16

Nếu bạn cần kiểm tra tốc độ và kiểu lúc xây dựng và chạy, phương thức trợ giúp này tốt hơn là sử dụng LINQ để truyền từng phần tử:

public static T[] GetEnumValues<T>() where T : struct, IComparable, IFormattable, IConvertible
{
    if (typeof(T).BaseType != typeof(Enum))
    {
        throw new ArgumentException(string.Format("{0} is not of type System.Enum", typeof(T)));
    }
    return Enum.GetValues(typeof(T)) as T[];
}

Và bạn có thể sử dụng nó như dưới đây:

static readonly YourEnum[] _values = GetEnumValues<YourEnum>();

Tất nhiên bạn có thể trở lại IEnumerable<T>, nhưng điều đó mua cho bạn không có gì ở đây.


3
Bắt đầu với C # 7.3 (Visual Studio 2017 v15.7), người ta có thể sử dụngwhere T: Enum
Yahoo Serious

14

Dưới đây là một ví dụ hoạt động về việc tạo các tùy chọn chọn cho DDL :

var resman = ViewModelResources.TimeFrame.ResourceManager;

ViewBag.TimeFrames = from MapOverlayTimeFrames timeFrame
      in Enum.GetValues(typeof(MapOverlayTimeFrames))
      select new SelectListItem
      {
         Value = timeFrame.ToString(),
         Text = resman.GetString(timeFrame.ToString()) ?? timeFrame.ToString()
      };

10
foreach (Suit suit in Enum.GetValues(typeof(Suit)))
{
}

(Câu trả lời được chấp nhận hiện tại có một dàn diễn viên mà tôi không nghĩ là cần thiết (mặc dù tôi có thể sai).)


10

Câu hỏi này xuất hiện trong Chương 10 của " C # Từng bước 2013 "

Tác giả sử dụng một vòng lặp đôi để lặp qua một cặp Số liệu (để tạo một bộ bài đầy đủ):

class Pack
{
    public const int NumSuits = 4;
    public const int CardsPerSuit = 13;
    private PlayingCard[,] cardPack;

    public Pack()
    {
        this.cardPack = new PlayingCard[NumSuits, CardsPerSuit];
        for (Suit suit = Suit.Clubs; suit <= Suit.Spades; suit++)
        {
            for (Value value = Value.Two; value <= Value.Ace; value++)
            {
                cardPack[(int)suit, (int)value] = new PlayingCard(suit, value);
            }
        }
    }
}

Trong trường hợp này, SuitValuecả hai bảng liệt kê:

enum Suit { Clubs, Diamonds, Hearts, Spades }
enum Value { Two, Three, Four, Five, Six, Seven, Eight, Nine, Ten, Jack, Queen, King, Ace}

PlayingCardlà một đối tượng thẻ có xác định SuitValue:

class PlayingCard
{
    private readonly Suit suit;
    private readonly Value value;

    public PlayingCard(Suit s, Value v)
    {
        this.suit = s;
        this.value = v;
    }
}

nó sẽ hoạt động nếu các giá trị trong enum không tuần tự?
Aamir Masood

10

Tôi biết nó hơi lộn xộn, nhưng nếu bạn là fan hâm mộ của một lớp lót, thì đây là một:

((Suit[])Enum.GetValues(typeof(Suit))).ToList().ForEach(i => DoSomething(i));


8

Điều gì sẽ xảy ra nếu bạn biết loại sẽ là một enum, nhưng bạn không biết loại chính xác là gì trong thời gian biên dịch?

public class EnumHelper
{
    public static IEnumerable<T> GetValues<T>()
    {
        return Enum.GetValues(typeof(T)).Cast<T>();
    }

    public static IEnumerable getListOfEnum(Type type)
    {
        MethodInfo getValuesMethod = typeof(EnumHelper).GetMethod("GetValues").MakeGenericMethod(type);
        return (IEnumerable)getValuesMethod.Invoke(null, null);
    }
}

Phương thức getListOfEnumsử dụng sự phản chiếu để lấy bất kỳ loại enum nào và trả về một IEnumerabletrong tất cả các giá trị enum.

Sử dụng:

Type myType = someEnumValue.GetType();

IEnumerable resultEnumerable = getListOfEnum(myType);

foreach (var item in resultEnumerable)
{
    Console.WriteLine(String.Format("Item: {0} Value: {1}",item.ToString(),(int)item));
}

8

Một cách đơn giản và chung chung để chuyển đổi một enum thành thứ gì đó bạn có thể tương tác:

public static Dictionary<int, string> ToList<T>() where T : struct
{
   return ((IEnumerable<T>)Enum
       .GetValues(typeof(T)))
       .ToDictionary(
           item => Convert.ToInt32(item),
           item => item.ToString());
}

Và sau đó:

var enums = EnumHelper.ToList<MyEnum>();

A Dictionarykhông phải là một ý tưởng hay: nếu bạn có lượt Enumthích enum E { A = 0, B = 0 }, giá trị 0 được thêm 2 lần tạo một ArgumentException(bạn không thể thêm tương tự Keytrên Dictionary2 lần trở lên!).
Massimiliano Kraus

Tại sao trả về a Dictionary<,>từ một phương thức có tên ToList? Ngoài ra tại sao không trở về Dictionary<T, string>?
Aluan Haddad

8

Thêm phương thức public static IEnumerable<T> GetValues<T>()vào lớp của bạn, như:

public static IEnumerable<T> GetValues<T>()
{
    return Enum.GetValues(typeof(T)).Cast<T>();
}

Gọi và vượt qua enum của bạn. Bây giờ bạn có thể lặp qua nó bằng cách sử dụng foreach:

 public static void EnumerateAllSuitsDemoMethod()
 {
     // Custom method
     var foos = GetValues<Suit>();
     foreach (var foo in foos)
     {
         // Do something
     }
 }

2

enumcác loại được gọi là "kiểu liệt kê" không phải vì chúng là các thùng chứa "liệt kê" các giá trị (mà chúng không có), mà bởi vì chúng được xác định bằng cách liệt kê các giá trị có thể cho một biến của loại đó.

(Trên thực tế, điều đó phức tạp hơn một chút - các loại enum được coi là có loại số nguyên "cơ bản", có nghĩa là mỗi giá trị enum tương ứng với một giá trị số nguyên (điều này thường ẩn, nhưng có thể được chỉ định thủ công). theo cách để bạn có thể nhét bất kỳ số nguyên của loại đó vào biến enum, ngay cả khi đó không phải là giá trị "được đặt tên".)

Các phương pháp System.Enum.GetNames có thể được sử dụng để lấy một mảng các chuỗi đó là tên của các giá trị enum, như tên gọi của nó.

EDIT: Nên đã đề xuất phương thức System.Enum.GetValues thay thế. Giáo sư.


2
Mặc dù câu trả lời của bạn là chính xác, nhưng nó không thực sự giải quyết câu hỏi ban đầu của OP. Các GetNamestrở về phương pháp, quả thật vậy, một mảng chuỗi, nhưng OP đòi hỏi một Enumerator thông qua các giá trị.
Silviu Preda

@SilviuPreda: Đã chỉnh sửa. Nó đáng lẽ phải là GetValues ​​thay vì GetNames.
Emily Chen

2

Tôi đã thử nhiều cách và nhận được kết quả từ mã này:

Để nhận danh sách int từ enum, hãy sử dụng như sau. Nó hoạt động!

List<int> listEnumValues = new List<int>();
YourEnumType[] myEnumMembers = (YourEnumType[])Enum.GetValues(typeof(YourEnumType));
foreach ( YourEnumType enumMember in myEnumMembers)
{
    listEnumValues.Add(enumMember.GetHashCode());
}

1
tanx để chỉnh sửa @ peter-mortensen
reza akhlaghi

0

Ngoài ra, bạn có thể liên kết với các thành viên tĩnh công khai của enum bằng cách sử dụng sự phản chiếu:

typeof(Suit).GetMembers(BindingFlags.Public | BindingFlags.Static)
    .ToList().ForEach(x => DoSomething(x.Name));

0

Nếu bạn có:

enum Suit
{
   Spades,
   Hearts,
   Clubs,
   Diamonds
}

Điều này:

foreach (var e in Enum.GetValues(typeof(Suit)))
{
    Console.WriteLine(e.ToString() + " = " + (int)e);
}

Sẽ xuất:

Spades = 0
Hearts = 1
Clubs = 2
Diamonds = 3

0

Cách chung của LINQ :

    public static Dictionary<int, string> ToList<T>() where T : struct =>
        ((IEnumerable<T>)Enum.GetValues(typeof(T))).ToDictionary(value => Convert.ToInt32(value), value => value.ToString());

Sử dụng:

        var enums = ToList<Enum>();
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.