开发者

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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜