关于c#:如何将泛型类型参数限制为System.Enum

How to limit a generic type parameter to System.Enum

本问题已经有最佳答案,请猛点这里访问。

Possible Duplicates:
Anyone know a good workaround for the lack of an enum generic constraint?
Create Generic method constraining T to an Enum

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

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

1
2
3
4
5
6
7
8
9
10
//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());
}

更新

我最终使用了乔恩·斯基特的无约束旋律。感谢你们的贡献。


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

1
2
3
4
5
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
2
3
4
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>();
}

丹尼回答的变化:

  • 尽管拥有一个泛型类型的参数允许进行类型推断,但由于实际上没有使用该值,因此更适合显式地指定泛型类型(例如,使用不带参数的Linq方法)。
  • getValues()返回一个对象数组,该数组不会隐式强制转换为t的IEnumerable。强制转换结果的额外Linq方法(从技术上讲,类型是一个筛选器操作,但在本例中,它将返回所有内容)必须符合返回类型。
  • 可选:尽管NotSupportedException与引发异常的任何选项一样好,但还有其他选项;ArgumentException、InvalidOperationException、InvalidCastException等。我选择InvalidOperationException是因为它是这样的;从非枚举类型获取枚举值的尝试无效。这是语义上的,我不会和任何其他人的逻辑争论。


不需要以这种方式使您的方法成为泛型方法。

您只需使用System.Enum作为返回类型中的类型参数:

1
2
3
4
5
6
7
8
using System.Linq;
.
.
.
public IEnumerable<Enum> GetValues(Enum value)
{
    return Enum.GetValues(value.GetType()).OfType<Enum>();
}