Простая форма класса Array и Enum.GetValues ()
Я работаю со статическим методом
Enum.GetValues(typeof(SomeEnum));
Этот метод отлично работает, когда все, что вам нужно сделать, это перечисление значений, но по какой-то причине оно возвращает очень простую форму класса Array. Я пытаюсь найти простой способ превратить его возвращаемое значение в более "нормальный" класс коллекции, такой как обычный массив или List < > .
До сих пор, если я хочу сделать это, я должен перечислить результат Enum.GetValues (typeof (SomeEnum)); и добавьте их один за другим в список < > .
Любые идеи, как сделать это более чисто?
Ответ:
Ключ должен отображать результат возврата -
SomeEnum[] enums = (SomeEnum[]) Enum.GetValues(typeof(SomeEnum));
Если вам нужен Список, тогда jus завершите его в скобках, а ToList - так:
List<SomeEnum> list = ((SomeEnum[]) Enum.GetValues(typeof(SomeEnum))).ToList();
Ответы
Ответ 1
I найденный здесь, вы можете просто сделать это:
SomeEnum[] enums = (SomeEnum[]) Enum.GetValues(typeof(SomeEnum));
И если вам нужен список, просто используйте .ToList() в конце, например:
List<SomeEnum> list = ((SomeEnum[]) Enum.GetValues(typeof(SomeEnum))).ToList();
Или, если вам нравится это лучше:
List<SomeEnum> list2 = new List<SomeEnum>((SomeEnum[]) Enum.GetValues(typeof(SomeEnum)));
Ответ 2
Если вы используете .NET 3.5, вы также можете использовать методы расширения Cast<T>
и ToList.
IEnumerable<SomeEnum> enums = Enum.GetValues(typeof(SomeEnum)).Cast<SomeEnum>();
Вы также можете получить список, если хотите
List<SomeEnum> list = Enum.GetValues(typeof(SomeEnum)).Cast<SomeEnum>().ToList();
Ответ 3
Вдохновленный Jon Skeet > unconstrained-melody, я придумал версия Мне больше нравится:
public static class Enum<T>
where T: struct
{
static Enum()
{
Trace.Assert(typeof(T).IsEnum);
Values = Array.AsReadOnly((T[])Enum.GetValues(typeof(T)));
}
public static readonly ReadOnlyCollection<T> Values;
}
и использование:
var values = Enum<BindingFlags>.Values;
Хорошо, что эта версия работает быстрее для нескольких вызовов, потому что она не создает новый массив каждый раз.
Ответ 4
У меня есть новая библиотека (UnconstrainedMelody), которая помогает в этом. Он может возвращать значения в строго типизированном массиве или в неизменяемом списке:
SomeEnum[] array = Enums<SomeEnum>.GetValuesArray()
IList<SomeEnum> list = Enums<SomeEnum>.GetValues();
Он общий и имеет ограничение на параметр типа, чтобы убедиться, что он действительно перечислил. Это невозможно в обычном С#, но библиотека немного размахивает, чтобы заставить его работать. Мне нравится вторая форма больше, потому что мы кэшируем список - тот факт, что он неизменен, означает, что мы можем снова и снова возвращать одну и ту же ссылку.
Существуют различные методы утилиты, облегчающие работу с перечислениями флагов и т.д.
Enjoy.
Ответ 5
ПЕРЕСМОТР (12-сентябрь-2009 ~ 2: 20 вечера EST):
Итак, я сделал это предложение вчера вечером на основе того, что Enum.GetValues
возвращает Array
, и я думал, что Array
реализует IEnumerable<T>
:
Я считаю, что вы можете построить List<T>
передавая любой IEnumerable<T>
как параметр в конструктор. Поэтому вы должны просто сделать это:
List<SomeEnum> values = new List<SomeEnum>(Enum.GetValues(typeof(SomeEnum)));
Тем не менее, GordonG довольно быстро ответил на мой ответ, указав, что он не компилируется. (Обычно я проверял свой ответ, но я был на компьютере без каких-либо инструментов разработки в то время, а также чувствовал себя [необоснованно] уверенным в себе.)
После некоторых downvotes и тяжелого поиска души я решил разобраться в этом вопросе (после хорошего ночного сна). В соответствии с документацией Microsoft по Array
классу здесь, Array
реализует IEnumerable<T>
, но только во время выполнения (так, а не во время компиляции - следовательно, неспособность скомпилировать). Это, оглядываясь назад, имеет смысл: Enum.GetValues
не является общим методом, и поэтому он не может знать, какую родовую коллекцию возвращаться заранее. (По крайней мере, как я это понимаю.)
В любом случае, все это означает, что вы можете юридически отнести Array
к IEnumerable<T>
при условии, что вы получите правильный тип. И вот, наконец, я могу представить свой окончательный ответ, который действительно такой же, как мой первоначальный ответ, но с простым броском, чтобы сделать все законным:
// splitting into two lines just for readability sake
List<SomeEnum> values;
values = new List<SomeEnum>((IEnumerable<T>) Enum.GetValues(typeof(SomeEnum)));
Конечно, в ретроспективе, GordonG не был мертв, чтобы получить List<T>
, что означает, что его собственный ответ на кастинг на SomeEnum[]
действительно так же хорош.
Ответ 6
Это должно работать:
List<MyEnum> enums = ((MyEnum[])Enum.GetValues(typeof(MyEnum))).ToList();
Причина, по которой ToList()
не работала в решении, которое вы отправили в своем вопросе, было то, что вам не хватает набора парнеров вокруг литой части. Надеюсь, это поможет!
Ответ 7
Обновленное решение (от 'Konstantin Spirin') для .NET framework 2.0:
public static class Enum<T> where T : struct
{
static Enum()
{
Trace.Assert(typeof(T).IsEnum);
}
public static ReadOnlyCollection<T> Values = new ReadOnlyCollection<T>(((T[])Enum.GetValues(typeof(T))));
}
Ответ 8
Как насчет этого:
List<SomeEnum> list = new List<SomeEnum>();
foreach (SomeEnum value in Enum.GetValues (typeof (SomeEnum)))
{
if (condition)
list.Add(value);
}