C # Iterasi melalui enum? (Mengindeks System.Array)


113

Saya memiliki kode berikut:

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

Namun, saya tidak dapat mengindeks nilai. Adakah cara yang lebih mudah untuk melakukan ini?

Atau apakah saya melewatkan sesuatu sama sekali!

Jawaban:


204
Array values = Enum.GetValues(typeof(myEnum));

foreach( MyEnum val in values )
{
   Console.WriteLine (String.Format("{0}: {1}", Enum.GetName(typeof(MyEnum), val), val));
}

Atau, Anda dapat mentransmisikan System.Array yang dikembalikan:

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

Tapi, dapatkah Anda yakin bahwa GetValues ​​mengembalikan nilai dalam urutan yang sama seperti GetNames mengembalikan nama?


3
"Tapi, dapatkah Anda yakin bahwa GetValues ​​mengembalikan nilai dalam urutan yang sama seperti GetNames mengembalikan nama?" - Ini adalah poin yang sangat bagus dan sesuatu yang belum saya bahas! Saya pikir solusi pertama Anda mungkin akan memberikan cara untuk mencocokkan nilai dan string dengan andal
TK.

Halo, saya pernah melihat penyebutan sebelumnya tentang kecurigaan "index-mismatching" yang terjadi saat melakukan ini; Namun, saya belum menemukan apakah ini benar-benar menjadi perhatian atau tidak? Adakah kasus definitif di mana asumsi ini bisa salah? Terima kasih!
Funka

Anda mungkin ingin mentransmisikan "val" kedua ke int, jika Anda ingin memecahkan masalah ketidakcocokan nilai seperti Enum.GetName(typeof(MyEnum), val), (int)val)di mana keluaran menyediakan nama dan nomor pencacahan.
Greg

GetValues ​​dan GetNames kembali dalam urutan yang sama, yaitu: "Elemen dari larik nilai yang dikembalikan diurutkan berdasarkan nilai biner dari konstanta yang disebutkan (yaitu, dengan besarnya unsigned)."
Russell Borogove

Saya yakin Anda juga dapat menggunakan LINQ secara langsung dengan Cast<T>melihat hasilnya:Enum.GetValues(typeof(MyEnum)).Cast<MyEnum>()...
jocull

33

Anda perlu mentransmisikan array - array yang dikembalikan sebenarnya dari tipe yang diminta, yaitu myEnum[]jika Anda meminta typeof(myEnum):

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

Lalu values[0]dll


9

Anda dapat mentransmisikan Array itu ke berbagai jenis Array:

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

atau jika Anda menginginkan nilai integer:

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

Anda tentu saja dapat mengulang larik yang dicor tersebut :)


7

Bagaimana dengan daftar kamus?

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

dan tentu saja Anda dapat mengubah tipe nilai kamus menjadi apa pun nilai enum Anda.


Saya pikir ini akan menjadi cara yang harus dilakukan, tetapi sayangnya enum berada di area kode yang tidak dapat saya kendalikan!
TK.

1
Satu-satunya solusi yang saya temukan yang mendapatkan nilai enum integer aktual!
SharpC

5

Solusi lain, dengan kemungkinan menarik:

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

Ini satu lagi. Kami memiliki kebutuhan untuk memberikan nama yang bersahabat untuk EnumValues ​​kami. Kami menggunakan System.ComponentModel.DescriptionAttribute untuk menampilkan nilai string kustom untuk setiap nilai 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;
    }
}

Digunakan

 public enum TestEnum
 { 
        [Description("Something 1")]
        Dr = 0,
        [Description("Something 2")]
        Mr = 1
 }



    static void Main(string[] args)
    {

        var vals = StaticClass.GetEnumFormattedNames<TestEnum>();
    }

Ini akan berakhir dengan mengembalikan "Sesuatu 1", "Sesuatu 2"


1
Hanya bagus jika deskripsinya statis ... jika deskripsi Anda perlu diubah berdasarkan instance, maka pendekatan ini tidak akan berfungsi.
Llyle

3

Bagaimana dengan menggunakan foreach loop, mungkin Anda bisa menggunakannya?

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

sesuatu seperti itu mungkin?


Saya telah mempelajari itu ... tetapi saya perlu mendapatkan akses ke nama dan nilai di 'sync' ... katakanlah nama [2] dipasangkan dengan nilai [2] dan saya tidak yakin bagaimana cara mencapainya di loop foreach!
TK.

Saya telah menambahkan contoh - lihat apakah itu membantu.
TWith2Sugars

3

Pertanyaan lama, tetapi pendekatan yang sedikit lebih bersih menggunakan LINQ .Cast<>()

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

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


2

Anda dapat menyederhanakan ini menggunakan string format. Saya menggunakan potongan berikut dalam pesan penggunaan:

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

Penentu format D memformat nilai enum sebagai desimal. Ada juga penentu X yang memberikan keluaran heksadesimal.

Penentu G memformat enum sebagai string. Jika atribut Flags diterapkan ke enum maka nilai gabungan juga didukung. Ada penentu F yang bertindak seolah-olah Bendera selalu ada.

Lihat Enum.Format ().


2

Dalam hasil Enum.GetValues, mentransmisikan ke int menghasilkan nilai numerik. Menggunakan ToString () menghasilkan nama yang akrab. Tidak diperlukan panggilan lain ke 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

Berikut adalah cara sederhana untuk mengulang melalui objek Enum kustom Anda

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

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

Next

1
Saya pikir OP meminta C #.
jm.

0

Pertanyaan kuno, tetapi jawaban 3Dave memberikan pendekatan termudah. Saya membutuhkan sedikit metode pembantu untuk menghasilkan skrip Sql untuk memecahkan kode nilai enum dalam database untuk debugging. Ini bekerja dengan baik:

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

Saya memilikinya dalam metode statis, jadi penggunaannya adalah:

var cheater = MyStaticClass.EnumToCheater<MyEnum>()
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.