C# Итерирование по перечислению? (Индексирование System.Array)
У меня есть следующий код:
// Obtain the string names of all the elements within myEnum
String[] names = Enum.GetNames( typeof( myEnum ) );
// Obtain the values of all the elements within myEnum
Array values = Enum.GetValues( typeof( myEnum ) );
// Print the names and values to file
for ( int i = 0; i < names.Length; i++ )
{
print( names[i], values[i] );
}
Однако я не могу индексировать значения. Есть ли более простой способ сделать это?
Или я что-то упустил полностью!
13 ответов
Array values = Enum.GetValues(typeof(myEnum));
foreach( MyEnum val in values )
{
Console.WriteLine (String.Format("{0}: {1}", Enum.GetName(typeof(MyEnum), val), val));
}
Или вы можете привести System.Array, который возвращается:
string[] names = Enum.GetNames(typeof(MyEnum));
MyEnum[] values = (MyEnum[])Enum.GetValues(typeof(MyEnum));
for( int i = 0; i < names.Length; i++ )
{
print(names[i], values[i]);
}
Но можете ли вы быть уверены, что GetValues возвращает значения в том же порядке, в котором GetNames возвращает имена?
Вам нужно привести массив - возвращенный массив на самом деле имеет запрошенный тип, т.е. myEnum[]
если вы попросите typeof(myEnum)
:
myEnum[] values = (myEnum[]) Enum.GetValues(typeof(myEnum));
затем values[0]
так далее
Вы можете привести этот массив к различным типам массивов:
myEnum[] values = (myEnum[])Enum.GetValues(typeof(myEnum));
или если вы хотите целочисленные значения:
int[] values = (int[])Enum.GetValues(typeof(myEnum));
Конечно, вы можете итерировать эти приведенные массивы:)
Как насчет списка словарей?
Dictionary<string, int> list = new Dictionary<string, int>();
foreach( var item in Enum.GetNames(typeof(MyEnum)) )
{
list.Add(item, (int)Enum.Parse(typeof(MyEnum), item));
}
и, конечно же, вы можете изменить тип значения словаря на любое значение перечисления.
Другое решение с интересными возможностями:
enum Days { Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday }
static class Helpers
{
public static IEnumerable<Days> AllDays(Days First)
{
if (First == Days.Monday)
{
yield return Days.Monday;
yield return Days.Tuesday;
yield return Days.Wednesday;
yield return Days.Thursday;
yield return Days.Friday;
yield return Days.Saturday;
yield return Days.Sunday;
}
if (First == Days.Saturday)
{
yield return Days.Saturday;
yield return Days.Sunday;
yield return Days.Monday;
yield return Days.Tuesday;
yield return Days.Wednesday;
yield return Days.Thursday;
yield return Days.Friday;
}
}
Старый вопрос, но немного более чистый подход с использованием LINQ .Cast<>()
var values = Enum.GetValues(typeof(MyEnum)).Cast<MyEnum>();
foreach(var val in values)
{
Console.WriteLine("Member: {0}",val.ToString());
}
Здесь другое. Нам нужно было предоставить дружественные имена для наших EnumValues. Мы использовали System.ComponentModel.DescriptionAttribute, чтобы показать пользовательское строковое значение для каждого значения перечисления.
public static class StaticClass
{
public static string GetEnumDescription(Enum currentEnum)
{
string description = String.Empty;
DescriptionAttribute da;
FieldInfo fi = currentEnum.GetType().
GetField(currentEnum.ToString());
da = (DescriptionAttribute)Attribute.GetCustomAttribute(fi,
typeof(DescriptionAttribute));
if (da != null)
description = da.Description;
else
description = currentEnum.ToString();
return description;
}
public static List<string> GetEnumFormattedNames<TEnum>()
{
var enumType = typeof(TEnum);
if (enumType == typeof(Enum))
throw new ArgumentException("typeof(TEnum) == System.Enum", "TEnum");
if (!(enumType.IsEnum))
throw new ArgumentException(String.Format("typeof({0}).IsEnum == false", enumType), "TEnum");
List<string> formattedNames = new List<string>();
var list = Enum.GetValues(enumType).OfType<TEnum>().ToList<TEnum>();
foreach (TEnum item in list)
{
formattedNames.Add(GetEnumDescription(item as Enum));
}
return formattedNames;
}
}
В использовании
public enum TestEnum
{
[Description("Something 1")]
Dr = 0,
[Description("Something 2")]
Mr = 1
}
static void Main(string[] args)
{
var vals = StaticClass.GetEnumFormattedNames<TestEnum>();
}
Это закончится возвратом "Нечто 1", "Нечто 2"
В результатах Enum.GetValues приведение к int приводит к числовому значению. Использование ToString() создает понятное имя. Никаких других вызовов Enum.GetName не требуется.
public enum MyEnum
{
FirstWord,
SecondWord,
Another = 5
};
// later in some method
StringBuilder sb = new StringBuilder();
foreach (var val in Enum.GetValues(typeof(MyEnum))) {
int numberValue = (int)val;
string friendyName = val.ToString();
sb.Append("Enum number " + numberValue + " has the name " + friendyName + "\n");
}
File.WriteAllText(@"C:\temp\myfile.txt", sb.ToString());
// Produces the output file contents:
/*
Enum number 0 has the name FirstWord
Enum number 1 has the name SecondWord
Enum number 5 has the name Another
*/
Как насчет использования цикла foreach, может быть, вы могли бы работать с этим?
int i = 0;
foreach (var o in values)
{
print(names[i], o);
i++;
}
что-то подобное возможно?
Вы можете упростить это, используя строки формата. Я использую следующий фрагмент в сообщениях об использовании:
writer.WriteLine("Exit codes are a combination of the following:");
foreach (ExitCodes value in Enum.GetValues(typeof(ExitCodes)))
{
writer.WriteLine(" {0,4:D}: {0:G}", value);
}
Спецификатор формата D форматирует значение перечисления как десятичное число. Также есть спецификатор X, который дает шестнадцатеричный вывод.
Спецификатор G форматирует перечисление как строку. Если к перечислению применяется атрибут Flags, то также поддерживаются комбинированные значения. Есть спецификатор F, который действует так, как будто Flags всегда присутствует.
Смотрите Enum.Format().
Массив имеет метод GetValue(Int32), который можно использовать для получения значения по указанному индексу.
Вот простой способ перебрать ваш собственный объект Enum
For Each enumValue As Integer In [Enum].GetValues(GetType(MyEnum))
Print([Enum].GetName(GetType(MyEnum), enumValue).ToString)
Next
Древний вопрос, но ответ 3Dave предоставил самый простой подход. Мне понадобился небольшой вспомогательный метод для генерации сценария Sql для декодирования значения enum в базе данных для отладки. Работало отлично:
public static string EnumToCheater<T>() {
var sql = "";
foreach (var enumValue in Enum.GetValues(typeof(T)))
sql += $@"when {(int) enumValue} then '{enumValue}' ";
return $@"case ?? {sql}else '??' end,";
}
У меня есть это в статическом методе, поэтому использование:
var cheater = MyStaticClass.EnumToCheater<MyEnum>()