2012-09-16 10 views
5

böyle bir enum Verilen: Ben bir IEnumerable bana vermesini aşağıdaki kodu kullanıyorumGenerics'i bir enum'dan IEnumerable yapma yöntemi oluşturmak için nasıl kullanabilirim?

public enum City { 
    London = 1, 
    Liverpool = 20, 
    Leeds  = 25 
} 

public enum House { 
    OneFloor = 1, 
    TwoFloors = 2 
} 

:

City[] values = (City[])Enum.GetValues(typeof(City)); 
var valuesWithNames = from value in values      
    select new { value = (int)value, name = value.ToString() }; 

kod ancak oldukça bir sürü için bunu yapmak zorunda çok iyi çalışıyor enums. Bunu yapmanın genel bir yolunu yaratmanın bir yolu var mı?

+1

Sorun, C# genel türlerinde enum 'kısıtlamalarına izin vermemesidir. Jon Skeet'in [kısıtsız melodisini] (http://code.google.com/p/unconstrained-melody/) kullanabilirsiniz. – Adam

+0

Sadece IEnumerable'a ihtiyacınız varsa çalışma zamanında kullanabilirsiniz. Aksi takdirde [templating] (http://msdn.microsoft.com/en-us/library/bb126445.aspx) VE yansımasını kullanmayı düşünebilirsiniz. – Guillaume

cevap

1

Bu fonksiyon size yardımcı olabilir:

public static IEnumerable<KeyValuePair<int, string>> GetValues<T>() where T : struct 
{ 
     var t = typeof(T); 
     if(!t.IsEnum) 
      throw new ArgumentException("Not an enum type"); 

     return Enum.GetValues(t).Cast<T>().Select (x => 
       new KeyValuePair<int, string>(
        (int)Enum.ToObject(t, x), 
        x.ToString())); 
} 

Kullanımı:

var values = GetValues<City>(); 
+0

'InvalidOperationException' * olarak tanımlandı *" Bir yöntem çağrısı, nesnenin geçerli durumu için geçersiz olduğunda atılan istisna."* Bu gerçekten yanıltıcı bir istisna gibi görünüyor. – Adam

+0

@codesparkle Belki de, 'SınırsızMelody * içinde tanımlanmış olanı gibi' ArgümanException ' – Magnus

+0

A' TypeArgumentException' için ideal olarak değiştirdim.Numara en yakın uygun istisna muhtemelen 'ArgumentException' olsa da ("Bir yönteme sağlanan argümanlardan biri geçerli olduğunda atılan istisna geçerli değildir.") * – Adam

1

Neden:

IEnumerable<object> GetValues<T>() 
    { 
     return Enum.GetValues(typeof (T)) 
        .Cast<T>() 
        .Select(value => new {  
              value = Convert.ToInt32(value), 
              name = value.ToString() 
             }); 

    } 

Yani kullanabilirsiniz:

var result = GetValues<City>(); 

Eğer enum olarak kısıt jenerik T yapmak istiyorsanız, enumjenerik contraint doğrudan olarak kullanılamaz çünkü, ancak enum, IConvertible arabiriminden miras alır, bu yolun iyi olduğuna inanın:

IEnumerable<object> GetValues<T>() where T: struct, IConvertible 
{} 

Dictionary tarafından IEnumerable<object> değiştirmek için:

Dictionary<int, string> GetValues<T>() where T : struct, IConvertible 
{ 
    return Enum.GetValues(typeof (T)).Cast<T>() 
       .ToDictionary(value => Convert.ToInt32(value), 
          value => value.ToString()); 
} 

Düzenleme: öğelerin sırası emin olmak gerekirse Magnus'un yorum olarak, sözlük seçenek değildir. Kendi güçlü tipinizi tanımlayın daha iyi olurdu.

+0

Sözlük döndürme ile ilgili iki sorun görüyorum: Önce sıralanmamış. İkinci olarak, eğer arama için kullanılmayacaksa bir sözlük döndürmek gereksizdir. – Magnus

+0

@Magnus: Unifieded ile doğru, neden kullanıyorum nedeni IEmmerable 'dan daha güçlüdür. –

3

Kullanım Jon Skeet en unconstrained melody.

using UnconstrainedMelody; 

Bir Dictionary<int, string> içine enum değerlerini koymak ve daha sonra üzerlerine numaralandırabilmesidir:

var valuesAsDictionary = Enums.GetValues<City>() 
           .ToDictionary(key => (int)key, value => value.ToString()); 

Ama muhtemelen hatta bunu yapmak gerekmez. Neden sadece değerleri doğrudan numaralandırılmıyor:

foreach (var value in Enums.GetValues<City>()) 
{ 
    Console.WriteLine("{0}: {1}", (int)value, value); 
} 
+0

Neden "int" değil "int" için döküm yapıyorsunuz? Enums ints olmak zorunda değilsiniz ve'yerine bir sözlük döndürememenizin bir nedeni yoktur. – Lee

+1

@Lee Sorunun içinde açıkça int ve string ister – Magnus

+0

@Lee ama sonra tekrar ihtiyacınız olan tüm bilgiler olduğunda neden bir sözlük oluşturmalısınız? enum değerinin kendisinde mi? Bu, cevabımın ikinci yarısında ifade etmeye çalıştığım nokta. – Adam

İlgili konular