如何将generics类型参数限制为System.Enum

可能重复:
任何人都知道缺乏枚举通用约束的好方法吗?
创建将T限制为枚举的通用方法

是否可以将Enum的generics类型参数[我不知道这是否是正确的名称]?

例如,我该如何做这样的事情?

 //VB.NET Function GetValues(Of T As System.Enum)(ByVal value As T) As IEnumerable(Of T) Return [Enum].GetValues(value.GetType) End Function //C# public IEnumerable GetValues(T value) where T : System.Enum { return Enum.GetValues(value.GetType()); } 

更新

我最终为此目的使用了Jon Skeet的无约束旋律 。 感谢大家的贡献。

不幸的是,你不能 – 微软关闭这个作为一个不会修复项目 。

您可以将枚举视为结构并将其用作约束(我认为Jon Skeet是如何在Unconstrained Melody中完成的 ?)但这有点不雅观。

你不能。 另一种解决方案是使用struct和运行时检查。

 public IEnumerable GetValues(T value) where T : struct { if (!typeof(T).IsEnum) throw new NotSupportedException(); return (IEnumerable)Enum.GetValues(value.GetType()); } 

Matt和Danny的答案都有一半的答案。 这实际上应该可以满足您的需求:

 public IEnumerable GetValues() where T : struct { if (!typeof(T).IsEnum) throw new InvalidOperationException("Generic type argument is not a System.Enum"); return Enum.GetValues(typeof(T)).OfType(); } 

Danny回答的变化:

  • 虽然具有generics类型的参数允许类型推断,但由于实际上没有使用该值,因此更明确地指定generics类型更合适(就像使用不带参数的Linq方法一样)。
  • Enum.GetValues()返回一个对象数组,它不会隐式地转换为T的IEnumerable。用于转换结果的额外Linq方法(技术上OfType是一个过滤操作,但在这种情况下它将返回所有内容)是必要的符合退货类型。
  • 可选:尽管NotSupportedException与抛出exception的选择一样好,但还有其他选项; ArgumentException,InvalidOperationException,InvalidCastException等。我选择了InvalidOperationException,因为它就是这样; 无效尝试从非枚举类型获取枚举值。 这是语义的,我不会与其他任何人的逻辑争论。

没有必要以这种方式使您的方法通用。

您可以在返回类型中使用System.Enum作为type参数:

 using System.Linq; . . . public IEnumerable GetValues(Enum value) { return Enum.GetValues(value.GetType()).OfType(); }