这是一个偶尔需要的特性。

正如我喜欢指出的那样,所有的特性都是无法实现的,直到有人设计、规范、实现、测试、文档和发布这些特性。到目前为止,还没有人这么做过。没有特别不寻常的理由为什么不; 我们有很多其他的事情要做,有限的预算,而且这一个从来没有超过“这不是很好吗?”语言设计团队的讨论。

CLR 不支持它,所以为了使它工作,除了语言工作之外,我们还需要做运行时工作。 (见回复评论)

我可以看到有一些像样的用例,但没有一个是如此引人注目,我们会做这项工作,而不是其他数以百计的功能,更频繁地要求,或有更引人注目和更深远的用例之一。(如果我们要修改这段代码,我个人会将委托约束的优先级排在枚举约束之上。)

事实上,这是可能的,用一个丑陋的把戏。 但是,它不能用于扩展方法。

public abstract class Enums<Temp> where Temp : class {
public static TEnum Parse<TEnum>(string name) where TEnum : struct, Temp {
return (TEnum)Enum.Parse(typeof(TEnum), name);
}
}
public abstract class Enums : Enums<Enum> { }


Enums.Parse<DateTimeKind>("Local")

如果愿意,可以为 Enums<Temp>提供一个私有构造函数和一个公共嵌套抽象继承类,其中 TempEnum,以防止非枚举的继承版本。

请注意,不能使用此技巧创建扩展方法。

这里有一件奇怪的事情,那就是您可能需要编写相当数量的通用 Enum 方法,它们的实现依赖于枚举的“基”类型。

通过枚举的“基本”类型 E,我指的是 System名称空间中的类型,其名称与通过对类型 E调用 System.Type.GetTypeCode(System.Type)而获得的 System.TypeCode枚举的成员名称相同。如果枚举是在 C # 中声明的,那么它就是声明“继承”的类型(我不确定这在规范中的正式名称是什么)。例如,下面的 Animal枚举的基类型是 System.Byte:

public enum Animal : byte
{
Moose,
Squirrel
}

使用 switch 语句编写这样的方法是可能的,但是它确实很难看,你不能得到强类型参数或者返回类型为枚举基类型的类型,你必须重复元数据查找或者做一些缓存(例如在包含方法的泛型类型的静态构造函数中)。

public static T GetEnum<T>(this string description) where T : struct
{
return (T)Enum.Parse(typeof(T), description);
}

这能回答你的问题吗?

下面是 SLaks 的丑陋把戏的 VB.NET 版本,Imports是“ typedef”: (类型推断按预期工作,但是无法获得扩展方法。)

'Base namespace "EnumConstraint"
Imports Enums = EnumConstraint.Enums(Of System.Enum)


Public NotInheritable Class Enums(Of Temp As Class)
Private Sub New()
End Sub


Public Shared Function Parse(Of TEnum As {Temp, Structure})(ByVal Name As String) As TEnum
Return DirectCast([Enum].Parse(GetType(TEnum), Name), TEnum)
End Function


Public Shared Function IsDefined(Of TEnum As {Temp, Structure})(ByVal Value As TEnum) As Boolean
Return [Enum].IsDefined(GetType(TEnum), Value)
End Function


Public Shared Function HasFlags(Of TEnum As {Temp, Structure})(ByVal Value As TEnum, ByVal Flags As TEnum) As Boolean
Dim flags64 As Long = Convert.ToInt64(Flags)
Return (Convert.ToInt64(Value) And flags64) = flags64
End Function


End Class


Module Module1


Sub Main()


Dim k = Enums.Parse(Of DateTimeKind)("Local")
Console.WriteLine("{0} = {1}", k, CInt(k))
Console.WriteLine("IsDefined({0}) = {1}", k, Enums.IsDefined(k))
k = DirectCast(k * 2, DateTimeKind)
Console.WriteLine("IsDefined({0}) = {1}", k, Enums.IsDefined(k))


Console.WriteLine(" {0} same as {1} Or {2}: {3} ", IO.FileAccess.ReadWrite, IO.FileAccess.Read, IO.FileAccess.Write, _
Enums.HasFlags(IO.FileAccess.ReadWrite, IO.FileAccess.Read Or IO.FileAccess.Write))


' These fail to compile as expected:
'Console.WriteLine(Enums.HasFlags(IO.FileAccess.ReadWrite, IO.FileOptions.RandomAccess))
'Console.WriteLine(Enums.HasFlags(Of IO.FileAccess)(IO.FileAccess.ReadWrite, IO.FileOptions.RandomAccess))


If Debugger.IsAttached Then _
Console.ReadLine()
End Sub


End Module

产出:

Local = 2
IsDefined(Local) = True
IsDefined(4) = False
ReadWrite same as Read Or Write: True

额外限制编织

你的准则

public static T GetEnum<[EnumConstraint] T>(this string description)
{
...
}

什么被编译

public static T GetEnum<T>(this string description) where T : Enum
{
...
}