为什么受"Enum"限制的泛型类型无法在C#7.3中被认定为"结构"?

Ste*_*edy 11 .net c# generics enums c#-7.3

如果我有一个带有这样的struct约束的泛型接口:

public interface IStruct<T> where T : struct { }
Run Code Online (Sandbox Code Playgroud)

我可以提供枚举作为我的类型T,因为enum满足struct约束:

public class EnumIsAStruct : IStruct<DateTimeKind> { }
Run Code Online (Sandbox Code Playgroud)

C#7.3增加了一个Enum约束.以下代码以前是非法的,现在编译:

public class MCVE<T> : IStruct<T> where T : struct, Enum { }
Run Code Online (Sandbox Code Playgroud)

但令我惊讶的是,以下内容无法编译:

public class MCVE<T> : IStruct<T> where T : Enum { }
Run Code Online (Sandbox Code Playgroud)

......有错误

CS0453类型'T'必须是非可空值类型才能在泛型类型或方法'IStruct'中将其用作参数'T'

为什么是这样?我希望受限制的泛型类型Enum可用作类型参数,其中类型受约束struct但似乎不是这种情况 - 我必须将Enum约束更改为struct, Enum.我的期望是错的吗?

Ste*_*edy 14

这个问题很奇怪(可以说),但是预期的行为.

System.Enum本身可以作为类型来提供T.作为一个班级,System.Enum当然不是一个struct!

public class MCVE<T> where T : Enum { }
public class MCVE2 : MCVE<Enum> { }
Run Code Online (Sandbox Code Playgroud)

正如贡献者HaloFour所解释的那样:

这是CLR本身的奇怪行为.System.Enum是一类,但每一个从派生类型System.Enumstruct.因此,约束System.Enum本身并不意味着struct因为您可以System.Enum作为泛型类型参数传递 ...

这很奇怪,但是简单地删除对编译器施加的限制比对可能具有不同行为的"枚举"约束的不同语法进行争论更容易.

解决方案是让你的标准的做法,限制在struct, Enum当你想限制具体类型是任何特定的枚举.如果另外你希望接受这个类System.Enum作为你的泛型类型,那么你才会约束Enum.

  • 我仍然想知道为什么不使用`enum`关键字来避免这种情况. (4认同)
  • 甚至不能像枚举一样使用它。无法转换为 (int) 且无法将值与“|”组合。使用 TEnum 通用值的唯一方法是使用 Convert.ToInt32 并使用整数,然后使用“(TEnum)(object)tenumValue”或“(TEnum)Enum.ToObject(enumType,tenumValue)”进行强制转换,并且ToObject 是一个糟糕的名称(应该是 FromValue),因为它被记录为从普通整数值创建 Enum 对象。有趣的是,即使不使用 Enum 类型约束功能,这个解决方法也能工作,所以它真的完全没用! (2认同)