Как перечислить перечисление

Как можно перечислить enum на C#?

Например. следующий код не компилируется:

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

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

И это дает следующую ошибку времени компиляции:

'Suit' is a 'type' but is used like a 'variable'

Он не работает по ключевому слову Suit, второму.

См. Также ... stackoverflow.com/questions/972307/…

SteveC 04.08.2009 18:10

Вы можете проверить тонкости перечислений C#, в котором обсуждается это, а также другие полезные лакомые кусочки enum

ChaseMedallion 14.05.2018 15:53
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
3 952
2
833 997
32
Перейти к ответу Данный вопрос помечен как решенный

Ответы 32

Я думаю ты можешь использовать

Enum.GetNames(Suit)
Ответ принят как подходящий

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

Примечание: приведение к (Suit[]) не является строго необходимым, но это делает код на 0,5 нс быстрее.

Это не работает, если у вас есть повторяющиеся значения в списке перечислителя.

Jessy 17.06.2012 07:50

@Jessy, если вам нужны все имена (включая имена с повторяющимися значениями), возможно, попробуйте Enum.GetNames в сочетании с Enum.Parse. Это будет немного медленным, я рекомендую сделать это один раз во время инициализации (или в первый раз, когда это необходимо) и кэшировать результаты в массив.

BrainSlugs83 13.08.2013 06:05

Я просто хочу отметить, что это, к сожалению, не будет работать в silverlight, поскольку библиотека silverlight не содержит enum.GetValues. В этом случае вы должны использовать отражение.

Giacomo Tagliabue 17.10.2013 09:50

@Jessy этот делает работает в случае повторяющихся ситуаций, таких как enum E {A = 0, B = 0}. Enum.GetValues возвращает два значения, хотя они и совпадают. E.A == E.B правда, так что разницы нет. Если вам нужны отдельные имена, вам следует искать Enum.GetNames.

nawfal 07.11.2013 13:25

Затем, если у вас есть дубликаты / синонимы в вашем перечислении, и вы хотите другое поведение, вы можете использовать расширение Linq Distinct (начиная с .NET 3.5), поэтому foreach (var suit in ((Suit[])Enum.GetValues(typeof(Suit))).Distinct()) { }.

Jeppe Stig Nielsen 12.06.2014 12:46

Я совершил ошибку, пытаясь использовать var в качестве типа. Компилятор сделает переменную Object вместо перечисления. Явно укажите тип перечисления.

jpmc26 09.01.2016 01:57

Когда я добавляю приведение (Suit[]), мой код запускается в 1,6 раза быстрее. Попробуй сам. Я тестировал пустой foreach с помощью StopWatch. for (int i = 0; i < 1000000; i++) foreach (Suit suit in (Suit[])Enum.GetValues(typeof(Suit))) {}

marbel82 09.06.2017 15:14

@BartoszKP Я запустил ваш код и обнаружил ошибку (ответил здесь). Я улучшил мои тесты с использованием теста BenchmarkDotNet.

marbel82 21.06.2018 00:31

@ marbel82 Молодец, спасибо! Это действительно квалифицируется как отдельный вопрос и ответ (вы можете ответить самостоятельно). Спасибо, что позволили мне кое-что узнать, это действительно очень интересно. Я отменил свое редактирование, поскольку похоже, что это правда - версия с приведением последовательно создает более быстрый код. Хотя ИМХО это все же квалифицируется как микрооптимизация, которая будет иметь смысл только в очень конкретных случаях.

BartoszKP 21.06.2018 12:05

Что ж, мне понравилось то, что вы указали, что Suit[] делает код На 0,5 нс быстрее :)

Momoro 14.02.2020 11:44

Мне кажется, что вы действительно хотите распечатать имена каждого перечисления, а не значения. В этом случае 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());
    }
}

Синтаксис VB здесь: связь

AndruWitta 09.09.2018 05:11

Я взял вашу версию с небольшими изменениями со своей стороны: Enum.GetValues(typeof(Suits)).OfType<Suits>().ToArray(). В этом случае я могу перебирать массив элементов перечисления Suits, а не строки.

Barabas 24.06.2019 15:57

@Barabas, почему бы просто не сделать Suits suit in Enum.GetValues(typeof(Suits))?

themadking 05.02.2020 01:15

@themadking о, чувак! конечно, использование точного типа выглядит лучше, чем этот чудовищный кусок кода ш ...!

Barabas 05.02.2020 14:41

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

Это перечисляет строку, не забудьте преобразовать эти вещи обратно в значение перечисления, чтобы перечисление можно было перечислить.

Ian Boyd 01.06.2010 21:46

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

Joshua Drake 04.06.2010 19:22

Я сделал несколько расширений для удобного использования 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
}

Однострочник для первого метода расширения; это не более ленивый. вернуть Enum.GetValues ​​(typeof (T)). Cast <T> ();

Leyu 22.06.2010 13:29

В качестве альтернативы вы также можете использовать OfType: Enum.GetValues ​​(typeof (T)). OfType <T> (). Жаль, что нет общей версии GetValues ​​<T> (), тогда было бы еще лучше.

jpierson 11.01.2011 01:38

Может кто подскажет, как пользоваться этими расширениями? Компилятор не показывает методы расширения для перечисления EnumExample.

Tomas 12.02.2013 12:01

@Tomas, вы поместили расширения в другое пространство имен? Вы добавили правильный оператор using?

bob 15.02.2013 15:24

+1 для многократно используемого кода: примеры - сохраните эти методы расширения в библиотеке и сделайте ссылку на нее [Флаги] public enum mytypes {name1, name2}; Список <строка> myTypeNames = mytypes.GetAllItems ();

Krishna 22.10.2013 10:55

Начиная с C# 7.3 (Visual Studio 2017 ≥ v15.7), можно использовать where T: Enum.

Yahoo Serious 27.07.2018 18:00

Некоторые версии платформы .NET не поддерживают Enum.GetValues. Вот хороший обходной путь от Идеи 2.0: Enum.GetValues ​​в 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;
}

Как и в случае с любым кодом, который включает отражение, вы должны предпринять шаги, чтобы убедиться, что он запускается только один раз, а результаты кэшируются.

Почему бы не использовать здесь ключевое слово yield вместо создания списка?

Eric Mickelsen 17.01.2011 01:18

или короче: return type.GetFields().Where(x => x.IsLiteral).Select(x => x.GetValue(null)).Cast<Enum>();

nawfal 07.11.2013 13:21

@nawfal: Linq недоступен .Net CF 2.0.

Gabriel GM 23.05.2014 19:16

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

I've heard vague rumours that this is terifically slow. Anyone know? – Orion Edwards Oct 15 '08 at 1:31 7

Я думаю, что кеширование массива значительно ускорит его. Похоже, вы каждый раз получаете новый массив (через отражение). Скорее:

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

Это хоть немного быстрее, да?

Однако компилятор должен позаботиться об этом.

Stephan Bijzitter 23.02.2015 15:57

@StephanBijzitter Вау, вы читаете об этом довольно далеко :-) Я согласен, компилятор должен сделать мое решение ненужным.

lmat - Reinstate Monica 23.02.2015 20:52

В этом нет необходимости. Глядя на скомпилированный код в ILSpy, компилятор определенно уже это делает. Почему за этот ответ проголосовали вообще не более 35 раз?

mhenry1384 08.05.2018 19:14

За него проголосовали давным-давно. Очень давно. Но я готов поспорить, что компилятор и тогда решил бы эту проблему. Но он уверен, что выглядит более производительный, не так ли? ;-)

lmat - Reinstate Monica 09.05.2018 19:58

Мое решение работает в .NET Compact Framework (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>();

как насчет использования T valueType = default(T)?

Oliver 07.07.2010 18:17

Отлично, я даже не знал этого ключевого слова. Всегда приятно узнать что-то новое. Спасибо! Всегда ли он возвращает ссылку на один и тот же объект или создает новый экземпляр при каждом вызове оператора по умолчанию? Я пока ничего не нашел в сети об этом, но если он каждый раз создает новый экземпляр, это как бы побеждает цель, которую я искал (наличие однострочного ^^).

Mallox 08.07.2010 10:48

Разве это не создавало бы новый экземпляр для каждой итерации перечисления?

Mallox 28.06.2011 19:04

-1 для «поддерживает проверку типа во время компиляции:». Какая проверка типа? Это будет работать для любого new()T. Кроме того, вам вообще не нужен new T(), вы можете выбрать только статические поля и использовать .GetValue(null). См. Ответ Обри.

nawfal 30.01.2014 08:47

Проверка типа во время компиляции относится к возвращаемому значению функции, которая в этом случае выдаст ошибку, если вы пытаетесь назначить перечисление списку другого типа. Некоторые из решений здесь возвращают универсальные шаблоны, которые не работают только во время выполнения.

Mallox 22.06.2015 21:47

Начиная с C# 7.3 (Visual Studio 2017 ≥ v15.7), можно использовать where T: Enum.

Yahoo Serious 27.07.2018 17:59

Вы не получите 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();
    }
}

Хорошее решение, но немного рефакторинга будет лучше! :)

nawfal 07.11.2013 13:10

Я использую .NET framework 4.0 и silverlight enum.getvalues, код, который я использовал, ---> enum.GetValues ​​(typeof (enum))

Ananda 30.12.2015 09:41

Начиная с C# 7.3 (Visual Studio 2017 ≥ v15.7), можно использовать where T: Enum.

Yahoo Serious 27.07.2018 17:59

Я думаю, что это более эффективно, чем другие предложения, потому что GetValues() не вызывается каждый раз, когда у вас есть цикл. Это также более лаконично. И вы получите ошибку времени компиляции, а не исключение времени выполнения, если 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]);
        }
    }
}

Будьте осторожны при использовании подобных дженериков. Если вы попытаетесь использовать EnumLoop с каким-либо типом, который не является перечислением, он будет компилироваться нормально, но вызовет исключение во время выполнения.

svick 06.02.2012 16:09

Спасибо, свик. Исключения времени выполнения фактически будут возникать с другими ответами на этой странице ... кроме этого, потому что я добавил «where Key: struct, IConvertible», чтобы в большинстве случаев вы получали ошибку времени компиляции.

James 07.02.2012 16:13

Нет, GetValues ​​() вызывается только один раз в foreach.

Alex Blokha 30.07.2012 15:25

Джеймс, я бы отговорил ваш класс, потому что умный - это хорошо писать, но в производственном коде, который многие люди будут поддерживать и обновлять, умный - это дополнительная работа. Если это дает значительную экономию или будет использоваться много - значит, экономия велика, и люди будут с ней знакомы - это того стоит, но в большинстве случаев это замедляет попытки людей читать и обновлять код и вводит возможные исходные ошибки в будущем. Чем меньше кода, тем лучше :) Чем меньше сложность, тем лучше.

Grant M 19.01.2015 07:00

@GrantM Почему? Этот код не является сложным и невероятно коротким. Кроме того, однократное написание класса позволит выполнять еще более короткие итерации кода с использованием его примера. Это очень чисто, если вы не можете обновить этот код, вы, вероятно, не сможете обновить какой-либо код компании.

Dispersia 16.05.2017 21:30

Начиная с C# 7.3 (Visual Studio 2017 ≥ v15.7), можно использовать where Key: Enum.

Yahoo Serious 27.07.2018 17:48

Я использую ToString (), затем разбиваю и разбираю массив слюны во флагах.

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

Вот рабочий пример создания опций выбора для 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()
      };

Я не придерживаюсь мнения, что это лучше или даже хорошо. Я просто предлагаю еще одно решение.

Если значения перечисления находятся в диапазоне строго от 0 до n - 1, общая альтернатива:

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

Если значения перечисления смежны и вы можете указать первый и последний элементы перечисления, тогда:

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

Но это не строго перечисление, просто цикл. Хотя второй метод намного быстрее, чем любой другой ...

Используйте Cast<T>:

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

Вот и все, IEnumerable<Suit>.

Это также работает в предложении from и деклараторе заголовка foreach.

Aluan Haddad 11.12.2017 14:58

Кажется, это самый чистый подход.

Jessica 24.11.2020 15:16

Для api "cast" требуется System.Linq. Мне просто не хватало актеров.

vikas pachisia 01.03.2021 13:19

Просто объединив основные ответы, я собрал очень простое расширение:

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

Это чисто, просто и, по комментарию @Jeppe-Stig-Nielsen, быстро.

Начиная с C# 7.3 (Visual Studio 2017 ≥ v15.7), можно использовать where T: Enum.

Yahoo Serious 27.07.2018 17:57

Три способа:

  1. Enum.GetValues(type) // Начиная с .NET 1.1, не в Silverlight или .NET Compact Framework
  2. type.GetEnumValues() // Только на .NET 4 и выше
  3. type.GetFields().Where(x => x.IsLiteral).Select(x => x.GetValue(null)) // Работает везде

Я не уверен, почему GetEnumValues был введен в экземплярах типов. Для меня это совсем не читается.


Наличие вспомогательного класса вроде Enum<T> - это то, что для меня наиболее читаемо и запоминается:

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

Теперь вы звоните:

Enum<Suit>.GetValues();

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

Можно также использовать какое-то кеширование, если производительность имеет значение, но я не думаю, что это вообще будет проблемой.

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

Это хороший обзор методов. Я думаю, вам следует объединить свой другой ответ с этим. На самом деле перечисления являются особенными, и их обход часто (обычно) так же действителен, как и перечисление, потому что вы знаете, что значения никогда не изменятся. IOW, если у вас есть перечисление, которое постоянно меняется, значит, вы для начала выбрали неправильную конструкцию данных.

krowe2 19.12.2017 20:03

Если вам нужна скорость и проверка типа во время сборки и выполнения, этот вспомогательный метод лучше, чем использование LINQ для приведения каждого элемента:

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

И вы можете использовать его, как показано ниже:

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

Конечно, вы можете вернуть IEnumerable<T>, но это вам ничего не даст.

Начиная с C# 7.3 (Visual Studio 2017 ≥ v15.7), можно использовать where T: Enum.

Yahoo Serious 27.07.2018 17:57

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

(Текущий принятый ответ имеет актерский состав, о котором я не думаю нужен (хотя могу ошибаться).)

Я знаю, что это немного беспорядочно, но если вы поклонник однострочных выражений, вот один из них:

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

Это шепелявить?

Mikael Dúi Bolinder 01.03.2019 18:02

Простой и универсальный способ преобразовать перечисление во что-то, с чем вы можете взаимодействовать:

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

А потом:

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

Dictionary - не лучшая идея: если у вас есть Enum, например enum E { A = 0, B = 0 }, значение 0 добавляется 2 раза, генерируя ArgumentException (вы не можете добавить тот же Key на Dictionary 2 или более раз!).

Massimiliano Kraus 25.10.2016 16:00

Зачем возвращать Dictionary<,> из метода с именем ToList? Также почему бы не вернуть Dictionary<T, string>?

Aluan Haddad 11.12.2017 14:53

Этот вопрос появляется в главе 10 "C# Шаг за шагом 2013"

Автор использует двойной цикл for для перебора пары перечислителей (для создания полной колоды карт):

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

В этом случае Suit и Value являются перечислениями:

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

а PlayingCard - это объект карты с определенными Suit и Value:

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

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

будет ли это работать, если значения в enum не являются последовательными?

Aamir Masood 01.02.2017 12:50

Что делать, если вы знаете, что тип будет enum, но не знаете, какой именно тип во время компиляции?

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

Метод getListOfEnum использует отражение для получения любого типа перечисления и возвращает IEnumerable всех значений перечисления.

Использование:

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

Есть два способа выполнить итерацию Enum:

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

Первый предоставит вам значения в форме массива ** object ** s, а второй даст вам значения в форме массива ** String ** s.

Используйте его в цикле foreach, как показано ниже:

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

Может быть, потому что это уже освещено во многих ответах? Не будем делать ответы лишними.

nawfal 17.05.2017 18:38

@nawfal yes может быть затронуто в других ответах, хотя в большинстве из них не завершено.

Kylo Ren 18.05.2017 08:39

Также вы можете напрямую связываться с общедоступными статическими членами перечисления, используя отражение:

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

Добавьте в свой класс метод public static IEnumerable<T> GetValues<T>(), например:

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

Позвоните и передайте свой enum. Теперь вы можете перебирать его, используя foreach:

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

Я бы добавил «where T: struct, Enum», чтобы ограничить метод перечислениями. Как этот общедоступный статический IEnumerable <T> ObtenerValores <T> (), где T: struct, Enum => Enum.GetValues ​​(typeof (T)). Cast <T> ();

Desmond 19.06.2020 22:00

Типы enum называются «перечислительными типами» не потому, что они являются контейнерами, которые «перечисляют» значения (а это не так), а потому, что они определяются перечисление как возможные значения для переменной этого типа.

(На самом деле это немного сложнее - считается, что типы перечислений имеют «базовый» целочисленный тип, что означает, что каждое значение перечисления соответствует целочисленному значению (обычно это неявно, но может быть указано вручную). C# был разработан таким образом, чтобы вы могли вставить целое число любой этого типа в переменную enum, даже если это не "именованное" значение.)

System.Enum.GetNames метод может использоваться для получения массива строк, которые являются именами значений перечисления, как следует из названия.

Обновлено: Вместо этого следовало предложить метод System.Enum.GetValues. Ой.

Хотя ваш ответ сам по себе правильный, он не отвечает на исходный вопрос OP. Метод GetNames действительно возвращает массив строк, но OP требует перечислителя для значений.

Silviu Preda 15.01.2018 12:30

@SilviuPreda: Отредактировано. Это должно было быть GetValues ​​вместо GetNames.

Emily Chen 16.01.2018 23:17

Чтобы получить список int из перечисления, используйте следующее. Оно работает!

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

Если у вас есть:

enum Suit
{
   Spades,
   Hearts,
   Clubs,
   Diamonds
}

Этот:

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

Выведет:

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

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

Использование:

        var enums = ToList<Enum>();

Новое решение .NET 5:

.NET 5 представил метод общая версия для GetValues:

Suit[] suitValues = Enum.GetValues<Suit>();

Использование в цикле foreach:

foreach (Suit suit in Enum.GetValues<Suit>())
{

}

что на данный момент является наиболее удобным решением.

Я думаю, это поможет вам попробовать.

public class Program
{

    public static List<T> GetEnamList<T>()
    {
        var enums = Enum.GetValues(typeof(T)).Cast<T>().Select(v => v).ToList();
        return enums;
    }
    private void LoadEnumList()
    {
        List<DayofWeek> dayofweeks = GetEnamList<DayofWeek>();

        foreach (var item in dayofweeks)
        {
            dayofweeks.Add(item);
        }
    }
}

    public enum DayofWeek
    {
        Monday,
        Tuesday,
        Wensday,
        Thursday,
        Friday,
        Sturday,
        Sunday
    }

Когда у вас есть немного такого перечисления

enum DemoFlags
{
    DemoFlag = 1,
    OtherFlag = 2,
    TestFlag = 4,
    LastFlag = 8,
}

С этим заданием

DemoFlags demoFlags = DemoFlags.DemoFlag | DemoFlags.TestFlag;

и нужен такой результат

"DemoFlag | TestFlag"

этот метод помогает:

public static string ConvertToEnumString<T>(T enumToConvert, string separator = " | ") where T : Enum
{
    StringBuilder convertedEnums = new StringBuilder();

    foreach (T enumValue in Enum.GetValues(typeof(T)))
    {
        if (enumToConvert.HasFlag(enumValue)) convertedEnums.Append($"{ enumValue }{separator}");
    }

    if (convertedEnums.Length > 0) convertedEnums.Length -= separator.Length;

    return convertedEnums.ToString();
}

Другие вопросы по теме