简体   繁体   English

IEnumerable的扩展方法 <Enum> ?

[英]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. 我为任何Enum编写了一个扩展方法,以获取Description属性(如果有)。 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. 我可以非常简单地使用它,它就像一个魅力,返回描述或ToString()按预期。

Here is the problem though. 这是问题所在。 I would like to have the ability to call this on an IEnumerable of MyEnum, YourEnum, or SomeoneElsesEnum. 我希望能够在IEnumerable的MyEnum,YourEnum或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: 我在这一点上找到的唯一答案是为泛型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

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? 有人必须有一个更好的答案,或解释为什么我可以扩展一个枚举但不是一个IEnumerable的枚举......任何人?

.NET generic covariance only works for reference types. .NET泛型协方差仅适用于引用类型。 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). 这里, MyEnum是一个值类型, System.Enum是一个引用类型(从枚举类型到System.Enum是一个装箱操作)。

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; 因此, IEnumerable<MyEnum>不是IEnumerable<Enum> ,因为这会将每个枚举项的表示从值类型更改为引用类型; 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. 从v4开始,C#支持通用接口和委托的协方差和反方差。 But unfortunately, these *-variances work only for reference types, it doesn't work for value types, such as enums. 但不幸的是,这些* - 方差仅适用于引用类型,它不适用于值类型,例如枚举。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM