Extension Methods for IEnumerable<Enum>?
I have a bunch of different enums, such as...
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
}
I wrote an extension method for any Enum to get the Description attribute if it has one. Simple enough right...
public static string GetDescription(this Enum currentEnum)
{
var fi = currentEnum.GetType().GetField(currentEnum.ToString());
var da = (DescriptionAttribute)Attribute.GetCustomAttribute(fi, typeof(DescriptionAttribute));
return da != null ? da.Description : currentEnum.ToString();
}
I can use this very simply and it works like a charm, returning the description or ToString() as expected.
Here is the problem though. I would like to have the ability to call this on an IEnumerable of MyEnum, YourEnum, or SomeoneElsesEnum. So I wrote the following extension just as simply.
public static IEnumerable<string> GetDescriptions(this IEnumerable<Enum> enumCollection)
{
return enumCollection.ToList().ConvertAll(a => a.GetDescription());
}
This doesn't work. It compiles fine as a method, but using it gives the following error:
Instance argument: cannot convert from 'System.Collections.Generic.IEnumerable<MyEnum>' to System.Collections.Generic.IEnumerable<System.Enum>'
So why is this? Can I make this work?
The only answer I have found at this point is to write extension methods for generic T as follows:
public static IE开发者_Python百科numerable<string> GetDescriptions<T>(this List<T> myEnumList) where T : struct, IConvertible
public static string GetDescription<T>(this T currentEnum) where T : struct, IConvertible
Someone must have a better answer for this, or an explanation of why I can extend an Enum but not an IEnumerable of Enum... Anyone?
.NET generic covariance only works for reference types. Here, MyEnum
is a value type, and System.Enum
is a reference type (casting from an enum type to System.Enum
is a boxing operation).
So, an IEnumerable<MyEnum>
is not an IEnumerable<Enum>
, as that would change the representation of each enumerated item from a value type to a reference type; only representation-preserving conversions are allowed. You need to use the generic method trick you've posted to get this to work.
Starting from v4 C# supports co-variance and contra-variance for generic interfaces and delegates. But unfortunately, these *-variances work only for reference types, it doesn't work for value types, such as enums.
精彩评论