Как можно перечислить 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, второму.
Вы можете проверить тонкости перечислений C#, в котором обсуждается это, а также другие полезные лакомые кусочки enum





Я думаю ты можешь использовать
Enum.GetNames(Suit)
foreach (Suit suit in (Suit[]) Enum.GetValues(typeof(Suit)))
{
}
Примечание: приведение к (Suit[]) не является строго необходимым, но это делает код на 0,5 нс быстрее.
Это не работает, если у вас есть повторяющиеся значения в списке перечислителя.
@Jessy, если вам нужны все имена (включая имена с повторяющимися значениями), возможно, попробуйте Enum.GetNames в сочетании с Enum.Parse. Это будет немного медленным, я рекомендую сделать это один раз во время инициализации (или в первый раз, когда это необходимо) и кэшировать результаты в массив.
Я просто хочу отметить, что это, к сожалению, не будет работать в silverlight, поскольку библиотека silverlight не содержит enum.GetValues. В этом случае вы должны использовать отражение.
@Jessy этот делает работает в случае повторяющихся ситуаций, таких как enum E {A = 0, B = 0}. Enum.GetValues возвращает два значения, хотя они и совпадают. E.A == E.B правда, так что разницы нет. Если вам нужны отдельные имена, вам следует искать Enum.GetNames.
Затем, если у вас есть дубликаты / синонимы в вашем перечислении, и вы хотите другое поведение, вы можете использовать расширение Linq Distinct (начиная с .NET 3.5), поэтому foreach (var suit in ((Suit[])Enum.GetValues(typeof(Suit))).Distinct()) { }.
Я совершил ошибку, пытаясь использовать var в качестве типа. Компилятор сделает переменную Object вместо перечисления. Явно укажите тип перечисления.
Когда я добавляю приведение (Suit[]), мой код запускается в 1,6 раза быстрее. Попробуй сам. Я тестировал пустой foreach с помощью StopWatch. for (int i = 0; i < 1000000; i++) foreach (Suit suit in (Suit[])Enum.GetValues(typeof(Suit))) {}
@BartoszKP Я запустил ваш код и обнаружил ошибку (ответил здесь). Я улучшил мои тесты с использованием теста BenchmarkDotNet.
@ marbel82 Молодец, спасибо! Это действительно квалифицируется как отдельный вопрос и ответ (вы можете ответить самостоятельно). Спасибо, что позволили мне кое-что узнать, это действительно очень интересно. Я отменил свое редактирование, поскольку похоже, что это правда - версия с приведением последовательно создает более быстрый код. Хотя ИМХО это все же квалифицируется как микрооптимизация, которая будет иметь смысл только в очень конкретных случаях.
Что ж, мне понравилось то, что вы указали, что Suit[] делает код На 0,5 нс быстрее :)
Мне кажется, что вы действительно хотите распечатать имена каждого перечисления, а не значения. В этом случае 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 здесь: связь
Я взял вашу версию с небольшими изменениями со своей стороны: Enum.GetValues(typeof(Suits)).OfType<Suits>().ToArray(). В этом случае я могу перебирать массив элементов перечисления Suits, а не строки.
@Barabas, почему бы просто не сделать Suits suit in Enum.GetValues(typeof(Suits))?
@themadking о, чувак! конечно, использование точного типа выглядит лучше, чем этот чудовищный кусок кода ш ...!
public void PrintAllSuits()
{
foreach(string suit in Enum.GetNames(typeof(Suits)))
{
Console.WriteLine(suit);
}
}
Это перечисляет строку, не забудьте преобразовать эти вещи обратно в значение перечисления, чтобы перечисление можно было перечислить.
Из вашего редактирования я вижу, что вы действительно хотите работать с самими перечислениями, приведенный выше код адресован вашему исходному сообщению.
Я сделал несколько расширений для удобного использования 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> ();
В качестве альтернативы вы также можете использовать OfType: Enum.GetValues (typeof (T)). OfType <T> (). Жаль, что нет общей версии GetValues <T> (), тогда было бы еще лучше.
Может кто подскажет, как пользоваться этими расширениями? Компилятор не показывает методы расширения для перечисления EnumExample.
@Tomas, вы поместили расширения в другое пространство имен? Вы добавили правильный оператор using?
+1 для многократно используемого кода: примеры - сохраните эти методы расширения в библиотеке и сделайте ссылку на нее [Флаги] public enum mytypes {name1, name2}; Список <строка> myTypeNames = mytypes.GetAllItems ();
Начиная с C# 7.3 (Visual Studio 2017 ≥ v15.7), можно использовать where T: Enum.
Некоторые версии платформы .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 вместо создания списка?
или короче: return type.GetFields().Where(x => x.IsLiteral).Select(x => x.GetValue(null)).Cast<Enum>();
@nawfal: Linq недоступен .Net CF 2.0.
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);
}
Это хоть немного быстрее, да?
Однако компилятор должен позаботиться об этом.
@StephanBijzitter Вау, вы читаете об этом довольно далеко :-) Я согласен, компилятор должен сделать мое решение ненужным.
В этом нет необходимости. Глядя на скомпилированный код в ILSpy, компилятор определенно уже это делает. Почему за этот ответ проголосовали вообще не более 35 раз?
За него проголосовали давным-давно. Очень давно. Но я готов поспорить, что компилятор и тогда решил бы эту проблему. Но он уверен, что выглядит более производительный, не так ли? ;-)
Мое решение работает в .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)?
Отлично, я даже не знал этого ключевого слова. Всегда приятно узнать что-то новое. Спасибо! Всегда ли он возвращает ссылку на один и тот же объект или создает новый экземпляр при каждом вызове оператора по умолчанию? Я пока ничего не нашел в сети об этом, но если он каждый раз создает новый экземпляр, это как бы побеждает цель, которую я искал (наличие однострочного ^^).
Разве это не создавало бы новый экземпляр для каждой итерации перечисления?
-1 для «поддерживает проверку типа во время компиляции:». Какая проверка типа? Это будет работать для любого new()T. Кроме того, вам вообще не нужен new T(), вы можете выбрать только статические поля и использовать .GetValue(null). См. Ответ Обри.
Проверка типа во время компиляции относится к возвращаемому значению функции, которая в этом случае выдаст ошибку, если вы пытаетесь назначить перечисление списку другого типа. Некоторые из решений здесь возвращают универсальные шаблоны, которые не работают только во время выполнения.
Начиная с C# 7.3 (Visual Studio 2017 ≥ v15.7), можно использовать where T: Enum.
Вы не получите 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 и silverlight enum.getvalues, код, который я использовал, ---> enum.GetValues (typeof (enum))
Начиная с C# 7.3 (Visual Studio 2017 ≥ v15.7), можно использовать where T: Enum.
Я думаю, что это более эффективно, чем другие предложения, потому что 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 с каким-либо типом, который не является перечислением, он будет компилироваться нормально, но вызовет исключение во время выполнения.
Спасибо, свик. Исключения времени выполнения фактически будут возникать с другими ответами на этой странице ... кроме этого, потому что я добавил «where Key: struct, IConvertible», чтобы в большинстве случаев вы получали ошибку времени компиляции.
Нет, GetValues () вызывается только один раз в foreach.
Джеймс, я бы отговорил ваш класс, потому что умный - это хорошо писать, но в производственном коде, который многие люди будут поддерживать и обновлять, умный - это дополнительная работа. Если это дает значительную экономию или будет использоваться много - значит, экономия велика, и люди будут с ней знакомы - это того стоит, но в большинстве случаев это замедляет попытки людей читать и обновлять код и вводит возможные исходные ошибки в будущем. Чем меньше кода, тем лучше :) Чем меньше сложность, тем лучше.
@GrantM Почему? Этот код не является сложным и невероятно коротким. Кроме того, однократное написание класса позволит выполнять еще более короткие итерации кода с использованием его примера. Это очень чисто, если вы не можете обновить этот код, вы, вероятно, не сможете обновить какой-либо код компании.
Начиная с C# 7.3 (Visual Studio 2017 ≥ v15.7), можно использовать where Key: Enum.
Я использую 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.
Кажется, это самый чистый подход.
Для api "cast" требуется System.Linq. Мне просто не хватало актеров.
Просто объединив основные ответы, я собрал очень простое расширение:
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.
Три способа:
Enum.GetValues(type) // Начиная с .NET 1.1, не в Silverlight или .NET Compact Frameworktype.GetEnumValues() // Только на .NET 4 и выше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, если у вас есть перечисление, которое постоянно меняется, значит, вы для начала выбрали неправильную конструкцию данных.
Если вам нужна скорость и проверка типа во время сборки и выполнения, этот вспомогательный метод лучше, чем использование 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.
foreach (Suit suit in Enum.GetValues(typeof(Suit)))
{
}
(Текущий принятый ответ имеет актерский состав, о котором я не думаю нужен (хотя могу ошибаться).)
Я знаю, что это немного беспорядочно, но если вы поклонник однострочных выражений, вот один из них:
((Suit[])Enum.GetValues(typeof(Suit))).ToList().ForEach(i => DoSomething(i));
Это шепелявить?
Простой и универсальный способ преобразовать перечисление во что-то, с чем вы можете взаимодействовать:
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 или более раз!).
Зачем возвращать Dictionary<,> из метода с именем ToList? Также почему бы не вернуть Dictionary<T, string>?
Этот вопрос появляется в главе 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 не являются последовательными?
Что делать, если вы знаете, что тип будет 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 yes может быть затронуто в других ответах, хотя в большинстве из них не завершено.
Также вы можете напрямую связываться с общедоступными статическими членами перечисления, используя отражение:
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> ();
Типы enum называются «перечислительными типами» не потому, что они являются контейнерами, которые «перечисляют» значения (а это не так), а потому, что они определяются перечисление как возможные значения для переменной этого типа.
(На самом деле это немного сложнее - считается, что типы перечислений имеют «базовый» целочисленный тип, что означает, что каждое значение перечисления соответствует целочисленному значению (обычно это неявно, но может быть указано вручную). C# был разработан таким образом, чтобы вы могли вставить целое число любой этого типа в переменную enum, даже если это не "именованное" значение.)
System.Enum.GetNames метод может использоваться для получения массива строк, которые являются именами значений перечисления, как следует из названия.
Обновлено: Вместо этого следовало предложить метод System.Enum.GetValues. Ой.
Хотя ваш ответ сам по себе правильный, он не отвечает на исходный вопрос OP. Метод GetNames действительно возвращает массив строк, но OP требует перечислителя для значений.
@SilviuPreda: Отредактировано. Это должно было быть GetValues вместо GetNames.
Чтобы получить список 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 представил метод общая версия для 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();
}
См. Также ... stackoverflow.com/questions/972307/…