Питання Як перерахувати перелік?


Як ви можете перерахувати enum в C #?

Наприклад, наступний код не складається:

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

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

І дає наступну помилку часу компіляції:

"Костюм" є "типом", але використовується як "змінна"

Це не вдається на Suit ключове слово, другий.


3118
2017-09-19 20:34


походження


Дивись також ... stackoverflow.com/questions/972307/... - SteveC
@ChaseMedallion Ваша посилання, здається, мертва. - Clearer
Ви можете перевірити входи і виходи з розширень C #, де йдеться про це, а також про інші корисні перечисні замітки - ChaseMedallion
@Clearer спасибі я оновив посилання. - ChaseMedallion


Відповіді:


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

3895
2017-09-19 20:37



Це не спрацює, якщо ви маєте повторювані значення у списку переліку. - Jessy
Я просто хочу наголосити, що це, на жаль, не буде працювати в сріблястому світлі, оскільки бібліотека Silverlight не включає в себе enum.GetValues. У цьому випадку потрібно використовувати відображення. - Giacomo Tagliabue
@ Джессі це робить працювати в разі повторення таких ситуацій, як enum E {A = 0, B = 0}. Enum.GetValues призводить до повернення двох значень, хоча вони однакові. E.A == E.B це правда, тому не існує розмежування. Якщо ви хочете індивідуальних імен, то вам слід шукати Enum.GetNames. - nawfal
Тоді, якщо ви маєте дублікати / синоніми у вашому переліку, і ви хочете, щоб інша поведінка, ви можете використовувати Linq Distinct розширення (з .NET 3.5), так foreach (var suit in ((Suit[])Enum.GetValues(typeof(Suit))).Distinct()) { }. - Jeppe Stig Nielsen
Я спробував використати помилку var для типу. Компілятор зробить змінну a Object замість enum. Перелічіть тип переліку явним чином. - jpmc26


Мені здається, що ви дійсно хочете надрукувати імена кожного переліку, а не цінності. У якому випадку Enum.GetNames() здається підходящим підходом.

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

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

До речі, приріст значення не є хорошим способом перелічити значення переліку. Ви повинні зробити це замість цього.

Я б користуюсь Enum.GetValues(typeof(Suit)) замість цього.

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

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

562
2017-09-19 20:39





Я зробив кілька розширень для зручного використання enum, може хтось може використовувати його ...

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

Сам перелік повинен бути прикрашений FlagsAttribute

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

287
2018-06-03 12:03



Один лайнер для першого методу розширення; це не ліньше. повернути Enum.GetValues ​​(typeof (T)). Cast <T> (); - Leyu
Як альтернатива, ви також можете використовувати OfType: Enum.GetValues ​​(typeof (T)). OfType <T> (). Це дуже погано, немає загальної версії GetValues ​​<T> (), то це буде ще більш витонченою. - jpierson
Може бути, хтось може показати, як використовувати ці розширення? Компілятор не показує методи розширення в enum EnumExample. - Tomas
Чи може хто-небудь додати приклад використання цих функцій? - Ashwini Verma
+1 для повторного коду: приклади - збережіть ці методи розширення в бібліотеці та вкажіть їх [Flags] public enum mytypes {name1, name2}; Список <string> myTypeNames = mytypes.GetAllItems (); - Krishna


Деякі версії .NET Framework не підтримуються Enum.GetValues. Ось хороший обхідний шлях Ідеї ​​2.0: Enum.GetValues ​​в Compact Framework:

public List<Enum> GetValues(Enum enumeration)
{
   List<Enum> enumerations = new List<Enum>();
   foreach (FieldInfo fieldInfo in enumeration.GetType().GetFields(
         BindingFlags.Static | BindingFlags.Public))
   {
      enumerations.Add((Enum)fieldInfo.GetValue(enumeration));
   }
   return enumerations;
}

Як і в будь-якому коді, який включає в себе рефлексія, вам слід вжити заходів, щоб забезпечити його виконання лише один раз, і результати кешуються.


147
2017-09-03 18:48



Чому б не використовувати ключове слово з виходом тут, а не екземплярувати список? - Eric Mickelsen
або коротше: return type.GetFields().Where(x => x.IsLiteral).Select(x => x.GetValue(null)).Cast<Enum>(); - nawfal
@nawfal: Linq недоступний. Net CF 2.0. - Gabriel GM
@Ekevoo Як пов'язати ці значення переліку з DropDownList у MVC? - Clint Eastwood


Я думаю, що це більш ефективно, ніж інші пропозиції, тому що GetValues() не викликається кожного разу, коли у вас є цикл. Це також більш короткий. І ви отримуєте помилку часу компіляції, а не виняток runtime, якщо Suit не є enum.

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

EnumLoop має це абсолютно загальне визначення:

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

85
2018-02-02 13:36



Обережно використовуйте генерику, як це. Якщо ви спробуєте використовувати EnumLoop з деяким типом, який не є переліком, він буде компілювати добре, але викинути виняток під час виконання. - svick
Дякую svick Винятки для виконання будуть насправді відбуватися з іншими відповідями на цій сторінці ... крім цього, тому що я додав "де Key: struct, IConvertible", так що у більшості випадків ви отримуєте помилку часу компіляції. - James
Ні, GetValues ​​() викликається лише один раз у попередньому вікні. - Alex Blokha
Джеймс, я б переконав вас у своєму класі, тому що розумно добре писати, але у виробничому коді, який багато людей підтримуватимуть і оновлюватимуть, розумні - це додаткова робота. Якщо це робить значну економію чи буде використано багато - так що заощадження великі, і люди знайомляться з нею - це варто, але в більшості випадків це сповільнює людей, які намагаються читати та оновлювати код і вводять можливий джерельних помилок у майбутньому. Менший код краще :) менш складність ще краще. - Grant M
@ Джеймс Не могли б ви надати прикладу для прив'язки цих переліків до DropDownList у MVC? - Clint Eastwood


Чому ніхто не користується Cast<T>?

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

Ось так IEnumerable<Suit>.


82
2018-03-17 04:15



Це досить круто, якщо ви можете використовувати LINQ ... - MemphiZ
Це також працює в from положення і foreach декларатор заголовка - Aluan Haddad


Ви не отримаєте Enum.GetValues() в Silverlight.

Оригінал публікації блогу Ейнара Інгебрігцена:

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

68
2017-11-17 01:29



Хороший розв'язок, але деякий рефакторинг буде кращим! :) - nawfal
@AubreyTaylor Не могли б ви надати прикладу для прив'язки цих переліків до DropDownList в MVC? - Clint Eastwood
Я використовую .NET Framework 4.0 & silverlight enum.getvalues ​​роботу, код я використав ---> enum.GetValues ​​(typeof (enum)) - Ananda
Починаючи з C # 7.3 (Visual Studio 2017 ≥ v15.7), можна використовувати where T: Enum - Yahoo Serious


Просто додати моє рішення, яке працює у компактній структурі (3.5) і підтримує перевірку типу під час компіляції:

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

- Якщо хтось знає, як позбутися T valueType = new T(), Я був би радий побачити рішення.

Виклик буде виглядати так:

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

50
2017-07-07 13:37



як щодо використання T valueType = default(T)? - Oliver
Відмінно, я навіть не знав цього ключового слова. Завжди приємно вчитися щось нове. Дякую! Чи завжди він повертає посилання на той самий об'єкт, чи створює він новий екземпляр щоразу, коли викликається типовий випадок? До цього часу я не знайшов нічого про цю мережу, але якщо він створює новий екземпляр кожен раз, це нагадує якусь мету, яку я шукав (маючи однокласник ^ ^). - Mallox
.GetValue (новий T ())? - Jason Miesionczek
Чи не створить це новий екземпляр для кожної ітерації за переліком? - Mallox
-1 для "підтримує перевірку типу під час компіляції:". Який тип перевірки? Це буде працювати для будь-якого new()  T. Також вам не потрібно new T()Ви взагалі можете вибрати лише статичні поля і робити це .GetValue(null). Див. Відповідь Обрі. - nawfal


Я думаю, що ви можете використовувати

Enum.GetNames(Suit)

44
2017-09-19 20:37



Enum.GetValues ​​(Костюми) - Ian Boyd


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

42
2017-09-19 21:05



Що перелічує рядок, не забудьте перетворити ці речі на значення переліку, щоб перерахувати перерахування. - Ian Boyd
Я бачу з вашого редагування, що ви хочете насправді працювати на самій псевдонімі, наведений вище код направив ваш оригінальний пост. - Joshua Drake