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

Ale*_*fie 28 .net c# vb.net enums

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

是否可以将泛型类型参数[我不知道这是否是正确的名称]限制为Enum

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

//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<T> GetValues<T>(T value) where T : System.Enum
{
    return Enum.GetValues(value.GetType());
}
Run Code Online (Sandbox Code Playgroud)

更新

为了这个目的,我最终使用了Jon Skeet的Unconstrained Melody.感谢大家的贡献.

Che*_*hen 16

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

public IEnumerable<T> GetValues<T>(T value) where T : struct
{  
    if (!typeof(T).IsEnum) throw new NotSupportedException();
    return (IEnumerable<T>)Enum.GetValues(value.GetType()); 
} 
Run Code Online (Sandbox Code Playgroud)


48k*_*ocs 7

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

您可以将枚举视为结构并将其用作约束(我认为Jon Skeet是如何在无约束旋律中完成的?)但这有点难看.

  • 感谢您指出乔恩·斯基特的《不受约束的旋律》。这非常有帮助。 (2认同)

Kei*_*thS 5

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

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

Danny回答的变化:

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