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

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

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

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

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

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

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

Не удалось выполнить ключевое слово Suit, второе.

вопрос задан 19.09.2008
Ian Boyd
114699 репутация

26 ответов


  • 3953 рейтинг
    foreach (Suit suit in (Suit[]) Enum.GetValues(typeof(Suit)))
    {
    }
    
    ответ дан jop, с репутацией 64061, 19.09.2008
  • 577 рейтинг

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

    Я сделал несколько расширений для простого использования enum, может быть, кто-то может использовать его. , ,

    public static class EnumExtensions
    {
        /// 
    /// Gets all items for an enum value. ///
     
        /// 
        /// 
    The value.
        /// 
        public static IEnumerable GetAllItems(this Enum value)
        {
            foreach (object item in Enum.GetValues(typeof(T)))
            {
                yield return (T)item;
            }
        }
    
        /// 
    /// Gets all items for an enum type. ///
     
        /// 
        /// 
    The value.
        /// 
        public static IEnumerable GetAllItems() where T : struct
        {
            foreach (object item in Enum.GetValues(typeof(T)))
            {
                yield return (T)item;
            }
        }
    
        /// 
    /// Gets all combined items from an enum value. ///
     
        /// 
        /// 
    The value.
        /// 
        /// 
        /// Displays ValueA and ValueB.
        /// 
        /// EnumExample dummy = EnumExample.Combi;
        /// foreach (var item in dummy.GetAllSelectedItems())
        /// {
        ///    Console.WriteLine(item);
        /// }
        /// 
        /// 
        public static IEnumerable GetAllSelectedItems(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;
                }
            }
        }
    
        /// 
    /// Determines whether the enum value contains a specific value. ///
        /// 
    The value.
        /// 
    The request.
        /// 
        ///     true if value contains the specified value; otherwise, false.
        /// 
        /// 
        /// 
        /// EnumExample dummy = EnumExample.Combi;
        /// if (dummy.Contains(EnumExample.ValueA))
        /// {
        ///     Console.WriteLine("dummy contains EnumExample.ValueA");
        /// }
        /// 
        /// 
        public static bool Contains(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;
        }
    }
    

    Сам перечислитель должен быть украшен атрибутом Flags

    [Flags]
    public enum EnumExample
    {
        ValueA = 1,
        ValueB = 2,
        ValueC = 4,
        ValueD = 8,
        Combi = ValueA | ValueB
    }
    
    ответ дан bob, с репутацией 5286, 3.06.2009
  • 150 рейтинг

    Некоторые версии. NET Framework не поддерживает Enum.GetValues. Вот хороший обходной путь от Идеи 2. 0: Enum. GetValues ​​в Compact Framework :

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

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

    ответ дан Ekevoo, с репутацией 1794, 3.09.2009
  • 85 рейтинг

    Я думаю, что это более эффективно, чем другие предложения, потому что GetValues() не вызывается каждый раз, когда у вас есть цикл. Это также более кратко. И вы получите ошибку времени компиляции, а не исключение времени выполнения, если Suit не является enum.

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

    EnumLoop имеет это полностью общее определение:

    class EnumLoop where Key : struct, IConvertible {
        static readonly Key[] arr = (Key[])Enum.GetValues(typeof(Key));
        static internal void ForEach(Action act) {
            for (int i = 0; i < arr.Length; i++) {
                act(arr[i]);
            }
        }
    }
    
    ответ дан James, с репутацией 2776, 2.02.2012
  • 82 рейтинг

    Почему никто не использует Cast?

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

    Там вы идете IEnumerable.

    ответ дан sircodesalot, с репутацией 6565, 17.03.2013
  • 68 рейтинг

    Вы не получите Enum.GetValues() в Silverlight.

    Оригинальное сообщение в блоге Einar Ingebrigtsen :

    public class EnumHelper
    {
        public static T[] GetValues()
        {
            Type enumType = typeof(T);
    
            if (!enumType.IsEnum)
            {
                throw new ArgumentException("Type '" + enumType.Name + "' is not an enum");
            }
    
            List values = new List();
    
            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 values = new List(); 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(); } } 
    ответ дан Aubrey Taylor, с репутацией 681, 17.11.2010
  • 50 рейтинг

    Просто чтобы добавить мое решение, которое работает в компактных рамках (3. 5) и поддерживает проверку типов во время компиляции :

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

    - Если кто-нибудь знает, как избавиться от T valueType = new T(), я был бы рад увидеть решение.

    Вызов будет выглядеть так:

    List result = Utils.GetEnumValues();
    
    ответ дан Mallox, с репутацией 1154, 7.07.2010
  • 44 рейтинг

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

    Enum.GetNames(Suit)
    
    ответ дан Tom Carr, с репутацией 1113, 19.09.2008
  • 42 рейтинг
    public void PrintAllSuits()
    {
        foreach(string suit in Enum.GetNames(typeof(Suits)))
        {
            Console.WriteLine(suit);
        }
    }
    
    ответ дан Joshua Drake, с репутацией 2236, 19.09.2008
  • 37 рейтинг
    foreach (Suit suit in Enum.GetValues(typeof(Suit))) { }
    

    Я слышал смутные слухи, что это очень медленно Кто-нибудь знает? - Орион Эдвардс 15 октября 2008 года в 1:31 7

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

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

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

    ответ дан Limited Atonement, с репутацией 4096, 16.11.2009
  • 21 рейтинг

    Три пути:

    1. Enum.GetValues(type) //since .NET 1.1, not in silverlight or compact framewok
    2. type.GetEnumValues() //only on .NET 4 and above
    3. type.GetFields().Where(x => x.IsLiteral).Select(x => x.GetValue(null)) //works everywhere
    

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


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

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

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

    Enum.GetValues();
    //or
    Enum.GetValues(typeof(Suit)); //pretty consistent style
    

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

    public static class Enum where T : struct, IComparable, IFormattable, IConvertible
    {
        //lazily loaded
        static T[] values;
        static string[] names;
    
        public static IEnumerable GetValues()
        {
            return values ?? (values = (T[])Enum.GetValues(typeof(T)));
        }
    
        public static IEnumerable GetNames()
        {
            return names ?? (names = Enum.GetNames(typeof(T)));
        }
    }
    
    ответ дан nawfal, с репутацией 40852, 12.08.2013
  • 20 рейтинг

    Что, черт возьми, я брошу свои два пенса, просто путем объединения лучших ответов я вместе очень простое расширение

    public static class EnumExtensions
    {
        /// 
    /// Gets all items for an enum value. ///
     
        /// 
        /// 
    The value.
        /// 
        public static IEnumerable GetAllItems(this Enum value)
        {
            return (T[])Enum.GetValues(typeof (T));
        }
    }
    

    Очистите просто и быстро с помощью комментария @ Jeppe-Stig-Nielsen.

    ответ дан Darkside, с репутацией 1320, 15.06.2013
  • 19 рейтинг

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

    [Flags]
    public enum ABC {
       a = 1,
       b = 2,
       c = 4
    };
    
    public IEnumerable 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);
    }
    
    ответ дан Mickey Perlstein, с репутацией 1213, 26.07.2012
  • 19 рейтинг

    Существует два способа перебора Enum:

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

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

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

    foreach(var value in values)
    {
        //Do operations here
    }
    
    ответ дан Kylo Ren, с репутацией 4923, 22.01.2016
  • 13 рейтинг

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

    public static T[] GetEnumValues() 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();
    

    Конечно, вы можете вернуть IEnumerable, но здесь вы ничего не купите.

    ответ дан dmihailescu, с репутацией 1162, 15.11.2013
  • 13 рейтинг

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

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

    public void EnumerateEnum()
    {
        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;
        }
    }
    

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

    ответ дан nawfal, с репутацией 40852, 25.01.2013
  • 11 рейтинг

    вот рабочий пример создания опций выбора для 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()
          };
    
    ответ дан jhilden, с репутацией 7656, 25.10.2012
  • 9 рейтинг
    foreach (Suit suit in Enum.GetValues(typeof(Suit)))
    {
    }
    

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

    ответ дан matt burns, с репутацией 16541, 20.01.2014
  • 8 рейтинг

    Этот вопрос появляется в главе 10 « C # Step by Step 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;
        }
    }
    
    ответ дан Ross Gatih, с репутацией 316, 28.06.2015
  • 6 рейтинг

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

    ((Suit[])Enum.GetValues(typeof(Suit))).ToList().ForEach(i => DoSomething(i));
    
    ответ дан anar khalilov, с репутацией 11331, 8.04.2014
  • 6 рейтинг

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

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

    А затем:

    var enums = EnumHelper.ToList();
    
    ответ дан Gabriel, с репутацией 774, 12.09.2014
  • 5 рейтинг

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

    public class EnumHelper
    {
        public static IEnumerable GetValues()
        {
            return Enum.GetValues(typeof(T)).Cast();
        }
    
        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));
    }
    
    ответ дан Slappywag, с репутацией 646, 1.10.2015
  • 1 рейтинг

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

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

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

     public static void EnumerateAllSuitsDemoMethod()
     {
         // custom method
         var foos = GetValues(); 
         foreach (var foo in foos)
         {
             // Do something
         }
     }
    
    ответ дан MUT, с репутацией 331, 31.03.2017
  • 0 рейтинг

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

    typeof(Suit).GetMembers(BindingFlags.Public | BindingFlags.Static)
        .ToList().ForEach(x => DoSomething(x.Name));
    
    ответ дан Termininja, с репутацией 4166, 9.01.2017
  • -1 рейтинг
    Типы

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

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

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

    РЕДАКТИРОВАТЬ: должны были предложить систему . Enum. Вместо этого используйте метод GetValues ​​. К сожалению.

    ответ дан Emily Chen, с репутацией 90, 11.10.2017