IEnumerable<Enum>的扩展方法?

4

我有许多不同的枚举类型,例如...

 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
}

我写了一个扩展方法,用于获取任何枚举类型的描述属性(如果有的话)。非常简单吧...

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

我可以很简单地使用这个,它像魔法一样工作,按预期返回描述或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

这个问题一定有更好的答案,或者是为什么我可以扩展枚举但不能扩展枚举的IEnumerable的解释... 有人知道吗?


自C# 7.3(从2018年开始),您可以将泛型约束写为where T:struct,System.Enum,这至少确保该方法仅与真正的枚举类型一起使用。 - Jeppe Stig Nielsen
2个回答

8
.NET泛型协变仅适用于引用类型。在这里,MyEnum是值类型,而System.Enum是引用类型(从枚举类型转换为System.Enum是一个装箱操作)。
因此,IEnumerable<MyEnum>不是IEnumerable<Enum>,因为这将把每个枚举项的表示从值类型更改为引用类型;只允许保留表示的转换。你需要使用你发布的通用方法技巧来使其工作。

0

从C# v4开始,泛型接口和委托支持协变性和逆变性。但不幸的是,这些* -variances仅适用于引用类型,对于枚举等值类型无效。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接