Вопрос по c#, .net – Как мне перечислить перечисление в C #?

3379

Как вы можете перечислить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 Ключевое слово, второй.

Вы можете проверитьthe ins and outs of C# enums, который обсуждает это, а также другие полезные лакомые кусочки ChaseMedallion
Смотрите также ...stackoverflow.com/questions/972307/… SteveC
У LOL точно такой же вопрос (угадайте, что вы хотите сделать с покером?): D julian bechtold

Ваш Ответ

26   ответов
48

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

Enum.GetNames(Suit)
Enum.GetValues (костюмы) Ian Boyd
44
public void PrintAllSuits()
{
    foreach(string suit in Enum.GetNames(typeof(Suits)))
    {
        Console.WriteLine(suit);
    }
}
Из ваших правок я вижу, что вы действительно хотите работать с самими перечислениями, приведенный выше код адресован вашему исходному сообщению.
Это перечисляет строку, не забудьте преобразовать эти вещи обратно в значение перечисления, чтобы перечисление могло быть перечислено. Ian Boyd
25

Три способа:

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

Not sure why was GetEnumValues introduced on type instance, it isn't very readable at all for me.


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

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

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

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

Если вам нужна проверка скорости и типа во время сборки и выполнения, этот вспомогательный метод лучше, чем использование 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 & # x2265; v15.7), можно использоватьwhere T: Enum
90

Я думаю, что это более эффективно, чем другие предложения, потому что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]);
        }
    }
}
Нет, GetValues () вызывается только один раз в foreach.
@James Не могли бы вы привести пример привязки значений перечисления к DropDownList в MVC?
Осторожнее с использованием таких дженериков. Если вы попытаетесь использоватьEnumLoop с некоторым типом, который не является enum, он прекрасно скомпилируется, но выдает исключение во время выполнения.
Джеймс, я бы не поощрял твой класс, потому что умный писать приятно, но в рабочем коде, который многие люди будут поддерживать и обновлять, умный - это дополнительная работа. Если это приводит к значительным сбережениям или будет использоваться много - таким образом, сбережения велики, и люди будут с ними знакомы - это того стоит, но в большинстве случаев это замедляет людей, пытающихся прочитать и обновить код, и представляет возможную источник ошибок в будущем. Чем меньше кода, тем лучше :), чем меньше сложность, тем лучше.
Спасибо, Свик. Во время других исключений на этой странице будут возникать исключения во время выполнения ... кроме этого, потому что я добавил & quot; где Key: struct, IConvertible & quot; так что вы получите ошибку времени компиляции в большинстве случаев.
7

Что делать, если вы знаете, что тип будет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));
}
43
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);
}

Это по крайней мере немного быстрее, да?

Это не обязательно. Глядя на скомпилированный код в ILSpy, компилятор определенно уже делает это. Почему за этот ответ вообще проголосовали, а тем более 35 раз?
Об этом должен позаботиться компилятор.
За это проголосовали очень давно. Давным-давно Я бы поспорил, что компилятор тоже решил бы это тогда. Но это точноlooks более производительный, не так ли? ;-)
@ StefBijzitter Ого, вы читаете довольно далеко об этом :-) Я согласен, компилятор должен сделать мое решение ненужным.
90

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

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

Там вы идетеIEnumerable<Suit>.

Это очень круто, если вы можете использовать LINQ ...
Это также работает вfrom пункт иforeach заголовок объявления.
1

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

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

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

РЕДАКТИРОВАТЬ: должны были предложитьSystem.Enum.GetValues метод вместо К сожалению.

Хотя ваш ответ верен сам по себе, он на самом деле не отвечает на первоначальный вопрос ФП.GetNames Метод возвращает действительно строковый массив, но OP требует перечислитель через значения.
@SilviuPreda: Отредактировано. Это должен был быть GetValues вместо GetNames.
4

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

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

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

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

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

((Suit[])Enum.GetValues(typeof(Suit))).ToList().ForEach(i => DoSomething(i));
В том, чтоlisp?
71

Вы не получите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();
    }
}
Хорошее решение, но некоторый рефакторинг будет лучше! :)
Я использую .NET Framework 4.0 & amp; Silverlight enum.getvalues работает, код, который я использовал, --- & gt; enum.GetValues (TypeOf (перечисление))
Начиная с C # 7.3 (Visual Studio 2017 & # x2265; v15.7), можно использоватьwhere T: Enum
15

I do not hold the opinion this is better, or even good, just stating yet another solution.

Если значения перечисления строго находятся в диапазоне от 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;
    }
}

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

53

Просто чтобы добавить мое решение, которое работает в компактной среде (3.5) и поддерживает проверку типовat compile time:

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>();
Разве это не создаст новый экземпляр для каждой итерации по перечислению?
-1 for & quot; поддерживает проверку типов во время компиляции: & quot ;. Какой тип проверки? Это будет работать для любогоnew() T, Кроме того, вам не нужноnew T() В общем, вы можете выбрать только статические поля и сделать.GetValue(null), Смотрите ответ Обри.
как насчет использованияT valueType = default(T)?
Начиная с C # 7.3 (Visual Studio 2017 & # x2265; v15.7), можно использоватьwhere T: Enum
Отлично, я даже не знал этого ключевого слова. Всегда приятно узнавать что-то новое. Спасибо! Всегда ли он возвращает ссылку на один и тот же объект или создает новый экземпляр каждый раз, когда вызывается оператор по умолчанию? До сих пор я не нашел в сети ничего об этом, но если он каждый раз создает новый экземпляр, это отчасти побеждает цель, которую я искал (наличие однострочника ^^).
22

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

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)
    {
        return (T[])Enum.GetValues(typeof (T));
    }
}

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

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

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

Сам enum должен быть украшенFlagsAttribute

[Flags]
public enum EnumExample
{
    ValueA = 1,
    ValueB = 2,
    ValueC = 4,
    ValueD = 8,
    Combi = ValueA | ValueB
}
Может быть, кто-то может показать, как использовать эти расширения? Компилятор не показывает методы расширения в enum Enample.
+1 для повторно используемого кода: примеры - сохранить эти методы расширения в библиотеке и сослаться на них [Flags] public enum mytypes {name1, name2}; Список & л; строка & GT; myTypeNames = mytypes.GetAllItems ();
Кто-нибудь может добавить пример, как использовать эти функции?
В качестве альтернативы вы также можете использовать OfType: Enum.GetValues (typeof (T)). OfType & lt; T & gt; (). Очень жаль, что нет универсальной версии GetValues & lt; T & gt; (), тогда она была бы еще более привлекательной.
162

Некоторые версии .NET Framework не поддерживают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;
}

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

или короче:return type.GetFields().Where(x => x.IsLiteral).Select(x => x.GetValue(null)).Cast<Enum>();
@Ekevoo Как связать значения перечисления с DropDownList в MVC?
Почему бы не использовать здесь ключевое слово yield вместо создания списка?
@nawfal: Linq недоступен .Net CF 2.0.
21

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

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

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

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<,> из метода с именемToList? Также почему бы не вернутьDictionary<T, string>?
Dictionary не очень хорошая идея: если у вас естьEnum лайкenum E { A = 0, B = 0 }, значение 0 добавляется 2 раза, генерируяArgumentException (вы не можете добавить то же самоеKey наDictionary 2 или более раз!).
4167
foreach (Suit suit in (Suit[]) Enum.GetValues(typeof(Suit)))
{
}

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

Это не сработает, если в списке перечислителей есть повторяющиеся значения.
Я просто хочу отметить, что это, к сожалению, не будет работать в Silverlight, поскольку библиотека Silverlight не содержитenum.GetValues, Вы должны использовать отражение в этом случае.
@ Джесси, этоdoes работать в случае дублирования ситуаций, таких какenum E {A = 0, B = 0}. Enum.GetValues приводит к возвращению двух значений, хотя они одинаковы.E.A == E.B верно, так что нет различия. Если вы хотите, чтобы отдельные имена, то вы должны искатьEnum.GetNames.
Я сделал ошибку, пытаясь использоватьvar для типа. Компилятор сделает переменнуюObject вместо перечисления. Перечислите тип перечисления явно.
Затем, если у вас есть дубликаты / синонимы в вашем перечислении, и вы хотите другое поведение, вы можете использовать Linq 'sDistinct расширение (начиная с .NET 3.5), такforeach (var suit in ((Suit[])Enum.GetValues(typeof(Suit))).Distinct()) { }.
21

Есть два способа перебора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
}
Может быть, потому что это уже описано во многих ответах? Давайте не будем делать ответы излишними.
понижение голосов даже без объяснения причин действительно несправедливо
Кто не голосует ... работает отлично ... и хотя бы добавить комментарий, что они считают неправильным?
@nawfal yes может быть рассмотрен в других ответах, хотя в большинстве из них он не очень удачен.
9

Этот вопрос появляется в главе 10 & quot;C # Шаг за Шагом 2013& Quot;

Автор использует двойной цикл 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 не являются последовательными?
10
foreach (Suit suit in Enum.GetValues(typeof(Suit)))
{
}

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

12

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

Похожие вопросы