C # Bir enum aracılığıyla yineleme? (System.Array dizini oluşturma)


113

Takip koduna sahibim:

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

Ancak değerleri endeksleyemiyorum. Bunu yapmanın daha kolay bir yolu var mı?

Ya da bir şeyi tamamen kaçırdım mı?

Yanıtlar:


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

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

Veya döndürülen System.Array'ı çevirebilirsiniz:

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

Ancak, GetNames'in adları döndürdüğü gibi GetValues'in değerleri aynı sırayla döndürdüğünden emin olabilir misiniz?


3
"Ancak, GetValues'in değerleri GetNames ile aynı sırayla döndürdüğünden emin misiniz?" - Bu çok iyi bir nokta ve henüz ele almam gereken bir konu! Sanırım ilk çözümünüz, değerleri ve dizeleri güvenilir bir şekilde eşleştirmenin bir yolunu sunacaktır
TK.

Merhaba, bunu yaparken ortaya çıkan bu "dizin uyuşmazlığı" şüphesinden daha önce bahsetmiştim; ancak, bunun gerçekten bir endişe olup olmadığını henüz keşfetmedim mi? Bu varsayımın ters gidebileceği kesin durumlar var mı? Teşekkürler!
Funka

Enum.GetName(typeof(MyEnum), val), (int)val)Çıktının numaralandırma adını ve numarasını sağladığı gibi değer uyuşmazlığını gidermek istiyorsanız, muhtemelen ikinci "val" yi bir int'e çevirmek istersiniz .
Greg

GetValues ​​ve GetNames aynı sırayla döner: "Dönüş değeri dizisinin öğeleri, numaralandırılmış sabitlerin ikili değerlerine göre sıralanır (yani, işaretsiz büyüklüklerine göre)."
Russell Borogove

Cast<T>Enum.GetValues(typeof(MyEnum)).Cast<MyEnum>()...
Sonucu

33

Sen dizi döküm gerekir - dönen dizi talep tipi, yani aslında myEnum[]sizin için sorarsanız typeof(myEnum):

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

Sonra values[0]vb.


9

Bu Diziyi farklı Dizi türlerine çevirebilirsiniz:

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

veya tamsayı değerlerini istiyorsanız:

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

Elbette bu döküm dizilerini yineleyebilirsiniz :)


7

Sözlük listesine ne dersiniz?

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

ve elbette sözlük değer türünü enum değerleriniz ne olursa olsun değiştirebilirsiniz.


Bence bu gidecek yol olabilir, ama ne yazık ki enum benim kontrol edemediğim bir kod alanında!
TK.

1
Gerçek tamsayı enum değerlerini alan bulduğum tek çözüm!
SharpC

5

İlginç olasılıklara sahip başka bir çözüm:

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

İşte başka. EnumValue'larımız için kolay isimler sağlamamız gerekiyordu. Her bir enum değeri için özel bir dize değeri göstermek için System.ComponentModel.DescriptionAttribute öğesini kullandık.

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

Kullanımda

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



    static void Main(string[] args)
    {

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

Bu, "Bir Şey 1", "Bir Şey 2" döndürerek sona erecek


1
Yalnızca açıklamalar statikse iyidir ... Açıklamalarınızın bir duruma göre değişmesi gerekiyorsa, bu yaklaşım işe yaramayacaktır.
Llyle

3

Bir foreach döngüsü kullanmaya ne dersiniz, belki bununla çalışabilirsiniz?

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

belki bunun gibi bir şey?


Bunu öğrettim ... ama 'senkronizasyonda' hem adlara hem de değerlere erişmem gerekiyor ... [2] adlarının [2] değerleriyle eşleştirildiğini ve bunu nasıl başaracağımdan emin değilim bir foreach döngüsü!
TK.

Bir örnek ekledim - bunun yardımcı olup olmadığına bakın.
TWith2Sugars

3

Eski soru, ancak LINQ'ları kullanarak biraz daha temiz bir yaklaşım .Cast<>()

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

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


2

Biçim dizelerini kullanarak bunu basitleştirebilirsiniz. Kullanım mesajlarında aşağıdaki parçacığı kullanıyorum:

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 biçimi belirticisi, enum değerini ondalık sayı olarak biçimlendirir. Ayrıca onaltılık çıktı veren bir X tanımlayıcısı da vardır.

G belirticisi, bir numaralandırmayı dizge olarak biçimlendirir. Flags özniteliği numaralandırmaya uygulanırsa, birleşik değerler de desteklenir. Bayraklar her zaman varmış gibi davranan bir F tanımlayıcısı vardır.

Bkz. Enum.Format ().


2

Enum.GetValues ​​sonuçlarında, int değerine çevrim sayısal değeri üretir. ToString () kullanmak kolay ad üretir. Enum.GetName için başka çağrı gerekmez.

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

İşte özel Enum nesnenizi yinelemenin basit bir yolu

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

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

Next

1
Bence OP, C # istedi.
jm.

0

Eski bir soru, ancak 3ave'nin cevabı en kolay yaklaşımı sağladı. Hata ayıklama için veritabanındaki bir enum değerini çözmek için bir Sql betiği oluşturmak için küçük bir yardımcı yönteme ihtiyacım vardı. Harika çalıştı:

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

Statik bir yöntemde var, bu yüzden kullanım:

var cheater = MyStaticClass.EnumToCheater<MyEnum>()
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.