C # Ітерація через енту? (Індексація System.Array)


113

У мене є такий код:

// 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] ); 
}

Однак я не можу індексувати значення. Чи є простіший спосіб зробити це?

Або я щось цілком пропустив!

Відповіді:


204
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 повертає імена?


3
"Але чи можете ви бути впевнені, що GetValues ​​повертає значення в тому ж порядку, коли імена GetNames повертає імена?" - Це дуже вдалий момент, і я ще маю звернути увагу! Я думаю, що ваше перше рішення, ймовірно, забезпечить спосіб надійного зіставлення значень і рядків
TK.

Привіт, я вже бачив згадування про цю підозру на "невідповідність індексу", що виникає при цьому; однак я ще не з'ясував, чи це насправді турбота чи ні? Чи є якісь остаточні випадки, коли це припущення може зірватися? Дякую!
Функа

Ви, ймовірно, хочете присвоїти другий "val" до int, якщо ви хочете усунути невідповідність значень, як у тому, Enum.GetName(typeof(MyEnum), val), (int)val)у якому на виході передбачено ім'я перерахування та число.
Грег

GetValues ​​та GetNames повертаються в тому самому порядку, а саме: "Елементи масиву повернених значень сортуються за бінарними значеннями перерахованих констант (тобто за їх безпідписаною величиною)."
Рассел Борогов

Я вважаю, що ви також можете використовувати LINQ безпосередньо, зателефонувавши Cast<T>на результат:Enum.GetValues(typeof(MyEnum)).Cast<MyEnum>()...
jocull

33

Вам потрібно передати масив - повернутий масив насправді потрібного типу, тобто myEnum[]якщо ви запитаєте typeof(myEnum):

myEnum[] values = (myEnum[]) Enum.GetValues(typeof(myEnum));

Потім values[0]тощо


9

Ви можете передавати цей масив різним типам масивів:

myEnum[] values = (myEnum[])Enum.GetValues(typeof(myEnum));

або якщо потрібно цілі значення:

int[] values = (int[])Enum.GetValues(typeof(myEnum));

Ви, звичайно, можете повторити ці литі масиви :)


7

Як щодо списку словників?

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

і, звичайно, ви можете змінити тип значення словника на будь-які значення перерахунків.


Я думаю, що це був би шлях, але, на жаль, перерахунок знаходиться у кодовій області, над якою я не маю контролю!
ТЗ.

1
Я знайшов єдине рішення, яке отримує фактичні цілі значення перерахунків!
SharpC

5

Ще одне рішення з цікавими можливостями:

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

4

Ось ще одна. У нас виникла потреба в наданні дружніх імен для наших EnumValues. Ми використовували System.ComponentModel.DescriptionAttribute для показу спеціального значення рядка для кожного значення enum.

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"


1
Тільки добре, якщо описи є статичними ... якщо ваші описи потрібно змінити на основі екземпляра, такий підхід не буде працювати.
Llyle

3

Що з використанням циклу foreach, можливо, ви могли б з цим працювати?

  int i = 0;
  foreach (var o in values)
  {
    print(names[i], o);
    i++;
  }

щось подібне, можливо?


Я це придушив ... але мені потрібно отримати доступ до імен та значень у "синхронізації" ... скажімо, імена [2] поєднані зі значеннями [2], і я не впевнений, як цього досягти петля передбачення!
ТЗ.

Я додав приклад - подивіться, чи це допомагає.
TWith2Sugars

3

Старе питання, але трохи більш чистий підхід із використанням LINQ .Cast<>()

var values = Enum.GetValues(typeof(MyEnum)).Cast<MyEnum>();

foreach(var val in values)
{
    Console.WriteLine("Member: {0}",val.ToString());     
}


2

Ви можете спростити це за допомогою рядків формату. Я використовую такий фрагмент у повідомленнях про використання:

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 формулює enum у вигляді рядка. Якщо атрибут Flags застосовано до enum, то також підтримуються комбіновані значення. Є специфікатор F, який діє так, ніби прапори завжди присутні.

Див. Enum.Format ().


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
 */

0

Ось простий спосіб перетворити ваш власний об’єкт Enum

For Each enumValue As Integer In [Enum].GetValues(GetType(MyEnum))

     Print([Enum].GetName(GetType(MyEnum), enumValue).ToString)

Next

1
Я думаю, що ОП попросив C #.
джм.

0

Стародавнє запитання, але відповідь 3Dave забезпечив найпростіший підхід. Мені знадобився трохи допоміжний метод для створення сценарію Sql для декодування значення перерахунку в базі даних для налагодження. Це спрацювало чудово:

    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>()
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.