IEnumerable的扩展方法?

发布于 2024-10-20 03:31:59 字数 1602 浏览 0 评论 0原文

我有一堆不同的枚举,例如...

 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 或 SomeElsesEnum 的 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 但不能扩展 Enum 的 IEnumerable ... 有人吗?

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 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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

三生一梦 2024-10-27 03:31:59

.NET 泛型协方差仅适用于引用类型。这里,MyEnum 是值类型,System.Enum 是引用类型(从枚举类型到 System.Enum 的转换是装箱)手术)。

因此,IEnumerable 不是 IEnumerable,因为这会将每个枚举项的表示从值类型更改为引用类型;只允许保留表示形式的转换。您需要使用您发布的通用方法技巧才能使其发挥作用。

.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.

梦开始←不甜 2024-10-27 03:31:59

从 v4 开始,C# 支持通用接口和委托的协变和逆变。但不幸的是,这些 *-变体仅适用于引用类型,不适用于值类型,例如枚举。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文