2011-03-02 14 views
4

私はそれが1つを持っている場合Description属性を取得するために、任意の列挙型の拡張メソッドを書いたようにIEnumerableの拡張メソッド<Enum>?

public enum MyEnum 
{ 
    [Description("Army of One")] 
    one, 
    [Description("Dynamic Duo")] 
    two, 
    [Description("Three Amigo's")] 
    three, 
    [Description("Fantastic Four")] 
    four, 
    [Description("The Jackson Five")] 
    five 
} 

...として、異なる列挙型の束を持っています。十分に簡単です...

これは非常に簡単に使用でき、魅力的に機能し、説明やToString()を期待通りに返します。

ここに問題があります。私はこれをMyEnum、YourEnum、SomeoneElsesEnumのIEnumerableで呼び出すことができます。だから私は次のような拡張機能をまったく簡単に書いています。

public static IEnumerable<string> GetDescriptions(this IEnumerable<Enum> enumCollection) 
{ 
    return enumCollection.ToList().ConvertAll(a => a.GetDescription()); 
} 

これは機能しません。これはメソッドとしてうまくコンパイルされますが、次のエラーが発生します。

Instance argument: cannot convert from 'System.Collections.Generic.IEnumerable<MyEnum>' to System.Collections.Generic.IEnumerable<System.Enum>' 

これはどうしてですか? 私はこの作品を作れますか?

私はこの時点で発見した唯一の答えは次のように一般的なTのための拡張メソッドを書くことです:

public static IEnumerable<string> GetDescriptions<T>(this List<T> myEnumList) where T : struct, IConvertible 
public static string GetDescription<T>(this T currentEnum) where T : struct, IConvertible 

誰かがこのためのより良い答え、または私は列挙型を拡張することができる理由の説明を持っている必要がありますEnumのIEnumerableではなく... 誰でも?

答えて

7

.NETの汎用共分散は参照型でのみ機能します。ここではMyEnumは値型で、System.Enumは参照型です(列挙型からSystem.Enumへのキャストはボクシング操作です)。

したがって、IEnumerable<MyEnum>は、それぞれの列挙項目の表現を値型から参照型に変更するため、IEnumerable<Enum>ではありません。表現を保存する変換のみが許可されます。これを動作させるには、投稿したジェネリックメソッドのトリックを使用する必要があります。

0

v4から始まるC#は、汎用インターフェイスと代理人の共分散とcontra-varianceをサポートしています。しかし残念なことに、これらのバリオンスは参照型に対してのみ機能し、enumなどの値型では機能しません。