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

时间:2011-02-21 15:23:25

标签: c# .net vb.net enums

  

可能重复:
  Anyone know a good workaround for the lack of an enum generic constraint?
  Create Generic method constraining T to an Enum

是否可以将通用类型参数[我不知道这是否是正确名称]限制为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());
}

更新

我最终为此目的使用了Jon Skeet的Unconstrained Melody。感谢大家的贡献。

4 个答案:

答案 0 :(得分: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()); 
} 

答案 1 :(得分:7)

不幸的是,你不能 - Microsoft closed this one out as a won't fix item

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

答案 2 :(得分:5)

马特和丹尼的答案都有一半的答案。这实际上应该可以满足您的需求:

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

Danny回答的变化:

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

答案 3 :(得分:2)

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

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

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