可能是重复问题:
有人知道缺少枚举泛型约束的好方法吗?
C#不允许在Enum
上设置类型约束的原因是什么?我相信这背后肯定有一种方法,但我想了解为什么不可能。
下面是我想要做的事情(理论上)。
public static T GetEnum<T>(this string description) where T : Enum
{
...
}
可能是重复问题:
有人知道缺少枚举泛型约束的好方法吗?
C#不允许在Enum
上设置类型约束的原因是什么?我相信这背后肯定有一种方法,但我想了解为什么不可能。
下面是我想要做的事情(理论上)。
public static T GetEnum<T>(this string description) where T : Enum
{
...
}
实际上,这是可能的,但需要使用一个不太雅观的技巧。 然而,它不能用于扩展方法。
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>
一个私有构造函数和一个公共嵌套抽象继承类,其中Temp
作为Enum
,以防止非枚举类型的继承版本。int
或 DateTime
。 - SLaksEnums<SomeOtherType>
(除了object
和ValueType
),这是唯一符合: class
且具有符合: struct
的子类型的类型。 - SLaks这是一个偶尔被请求的功能。
正如我经常指出的那样,所有的功能在有人设计、规格化、实现、测试、文档化和发布之前都是未实现的。到目前为止,没有人为此做过这些工作。并没有什么特别不寻常的原因;我们有很多其他事情要做,预算有限,而且这个功能从未超过语言设计团队的“这会很好吧?”讨论。
CLR不支持它,所以为了使其工作,除了语言工作外,我们还需要进行运行时工作。(请参见答案评论)
我可以看到有一些不错的使用案例,但没有一个是如此引人注目,以至于我们会为此工作,而不是处理更频繁请求或具有更强大和广泛使用案例的数百个其他功能。(如果我们要搞乱这段代码,我个人会将委托约束置于枚举约束之上。)
Delegate
的。如果这意味着可以从C# 5中移除限制,我很乐意进行更多(甚至是大量)的实验。(我假设C# 4现在已经被锁定了。) - Jon Skeetpublic static T GetEnum<T>(this string description) where T : struct
{
return (T)Enum.Parse(typeof(T), description);
}
这是否回答了你的问题?
if (!typeof(T).IsEnum) { throw new InvalidOperationException("MethodBlah需要一个枚举!"); }
- BrainSlugs83使用ExtraConstraints进行IL编织。
public static T GetEnum<[EnumConstraint] T>(this string description)
{
...
}
public static T GetEnum<T>(this string description) where T : Enum
{
...
}
这是VB.NET版本的SLaks的优秀丑陋技巧,使用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
System.Type.GetTypeCode(System.Type)
获取 E
类型的 System.TypeCode
枚举成员的名称相同的位于 System
命名空间中的类型。如果该枚举是在 C# 中声明的,则它与其“继承”的类型相同(我不确定规范中是否正式称其为什么)。例如,下面的 Animal
枚举的基础类型是 System.Byte
:public enum Animal : byte
{
Moose,
Squirrel
}
where T : struct, Enum
作为限制条件 - VBWebProfiwhere T : struct, Enum
作为限制条件 - undefined