C# 7.3 枚举约束:为什么不能使用枚举关键字?

28
为了将一个通用类型参数限制为枚举类型,我以前会像这样进行约束,这是在 C# 7.3 之前限制枚举类型 T 的最佳方法:
void DoSomething<T>() where T : struct, IComparable, IConvertible, IFormattable

现在,C# 7.3 添加了一个新功能,用于将泛型类型限制为 System.Enum

我尝试使用今天发布的VS2017 15.7更新与枚举约束一起使用,并写成以下形式时编译成功(假设我有一个using System;指令):

void DoSomething<T>() where T : Enum

然而,使用enum关键字是不起作用的,会导致编译器抛出以下错误(后面还有更多错误,期望一个方法体,但在这里我想没有必要提到):

void DoSomething<T>() where T : enum
                                ^ error CS1031: Type expected
                                  error CS1002: ; expected
                                    ^ error CS1001: Identifier expected
                                      error CS1514: { expected
                                      error CS1513: } expected

由于有一个适用于结构体的struct约束,我不明白为什么enum不能像结构体那样在此处使用。确实,enum不会像int对于Int32那样映射到实际类型,但我认为它应该像struct约束一样运作。

我是不是掉进了一个还没有完全实现的实验性功能陷阱里,或者这是在规范中故意这样做的(为什么)?


虽然 stringString 类型的别名,但是对于 enum 关键字和 Enum 类型并非如此。 - user47589
这就是我在上一个段落中所说的意思。struct 约束并不是特定类型的别名,但是它是可能的。 - Ray
struct 用于值类型,不仅限于 struct,类似于所有引用类型的 class - Mrinal Kamboj
请检查这个链接,可能是一个解决方案。https://dev59.com/53VD5IYBdhLWcg3wHn2d#79903 - Mrinal Kamboj
@MrinalKamboj 这有点说得通。虽然我认为人们可以争论那些关键字处理它们自己的特定情况,而 enum 也应该这样做。关于你的链接:使用 C# 7.3,现在使用 Enum(而不是关键字 enum)将是更好的解决方案。问题只是为什么这个关键字目前不能工作。 - Ray
这个实现让我感到困惑。我的问题为什么一个被'Enum'约束的泛型不能作为'struct'合格?可能会引起兴趣 :) - Stephen Kennedy
1个回答

18
泛型上的struct约束没有映射到实际类型(尽管在理论上,它可以映射到ValueType)。同样,enum也不像stringintlong那样干净地映射到实际类型,而是设置了特殊的语法来创建一个符号常量类,这些常量映射到整数值;因此使用public enum Stuff而不是public class Stuff : Enum。请注意,如果后者被实现,它会更加微妙,因为它会基于继承类型而改变语法,而不是基于非class关键字而改变语法。
因此,总之,是的,where T: enum不能正常工作,因为enum是一个关键字,而不是类型别名。如果您真的想让它起作用,因为在这种情况下enum至少看起来像是一个类型别名,请提出请求!
编辑:对于一些历史参考,这里是一个来自2008年的问题,表明Enum不是一个有效的约束,因为它是一个特殊的类。

我想这是目前为止最好的解释了。我在GitHub上找不到其他讨论此功能实现的示例。有趣的是,那里的人们最初提供的示例也使用了“enum”关键字,但最终并没有像那样实现。 - Ray
3
@RayKoopa,如果您只使用了where T : Enum,那么我有点惊讶编译器允许您将抽象基类型System.Enum本身(一个引用类型!)用作T。 因此,您可以执行DoSomething<Enum>();。为了避免这种情况,实际上是合法的where T : struct,Enum。对我来说,99.9%的时间看起来就是这样!啊,我现在看到有一个关于这个问题的链接线程。 - Jeppe Stig Nielsen

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接