2012-09-16 2 views
5

このような列挙型を考える:しかし、私は非常に多くのためにこれをしなければならないGenericsを使用してIEnumerableを列挙型にする方法を作成するにはどうすればよいですか?

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

コードは非常に良い作品:

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

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

私は私のIEnumerableを与えるために、次のコードを使用していますenums。これを行う一般的な方法を作成する方法はありますか?

+1

問題は、C#ではジェネリック型に 'enum'制約が認められないということです。あなたはJon Skeetの[拘束されていないメロディ](http://code.google.com/p/unconstrained-melody/)を使うことができます。 – Adam

+0

実行時にのみ 'IEnumerable'が必要な場合は、リフレクションを使用できます。そうでなければ、[templating](http://msdn.microsoft.com/en-us/library/bb126445.aspx)とリフレクションの使用を検討することもできます。 – Guillaume

答えて

1

この機能はあなたを助けるかもしれない:

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

使用法:

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

'InvalidOperationException'は次のように定義されています*"オブジェクトの現在の状態に対してメソッド呼び出しが無効である場合にスローされる例外です。"*これは本当に間違っている例外のように思えます。 – Adam

+0

おそらく、私はそれを' ArgumentException'に変更しました。 – Magnus

+0

* UnconstrainedMelody *で定義されているような 'TypeArgumentException'が理想的です。 'ArgumentException'しかし*("メソッドに提供された引数の1つが有効でないときにスローされる例外 ")* – Adam

1

なぜ:

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

    } 

あなたが使用することができます。

var result = GetValues<City>(); 

enumが直接ジェネリックcontraintとして使用することはできませんので、あなたが、enumなどの制約ジェネリックTを作りたい場合は、 enumはインターフェイスIConvertibleから継承していますが、この方法は問題ありません。

IEnumerable<object>を交換するには
IEnumerable<object> GetValues<T>() where T: struct, IConvertible 
{} 

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

編集:あなたがアイテムの順序を確認する必要がある場合は、マグナスさんのコメントのように、辞書はオプションではありません。あなた自身の強いタイプを定義する方が良いでしょう。

+0

辞書を返すことには2つの問題があります。まず、順序付けされていません。次にルックアップに使用されない場合は、辞書を返す必要はありません。 – Magnus

+0

@Magnus:順不同で真、なぜ辞書はIEmmerable よりも強力な型です。 –

3

使用ジョンスキートのunconstrained melody

using UnconstrainedMelody; 

あなたはDictionary<int, string>にあなたの列挙型の値を配置し、それらの上に列挙することができます。

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

しかし、あなたはおそらくそれをする必要はありません。なぜ値を直接列挙するだけではないのですか?

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

なぜ' T'ではなく 'int'にキャストしていますか?列挙型はintである必要はありませんなぜなら、あなたは 'Dictionary 'を代わりに返すことはできません。 – Lee

+1

@Lee質問では、明示的にintとstringが必要です。 – Magnus

+0

@Leeしかし、もう一度、必要なすべての情報が存在する列挙値そのものの中でこれは私の答えの後半に表現しようとした点です。 – Adam

関連する問題