C# 为什么这个枚举声明现在可以工作?
在回答另一个问题时,Jon Skeet提到,C# 为什么这个枚举声明现在可以工作?,c#,.net,enums,c#-6.0,C#,.net,Enums,C# 6.0,在回答另一个问题时,Jon Skeet提到,enums的定义有一个奇怪的地方 他指出,重新定义enum的基础类型只能使用类型别名,而不能使用框架类型(int有效,Int32无效,等等) 现在,我试图重现这一点(VS2015中的C#6/Roslyn),但我没有得出相同的结论: public enum TestEnum : UInt32 { } 及 两者都是完全有效的。为什么会这样?还是什么改变了 编辑: 所以为了澄清问题,这是C#6中的一个变化,还没有被记录下来,而且很快就会被记录下来,你可
enums
的定义有一个奇怪的地方
他指出,重新定义enum
的基础类型只能使用类型别名,而不能使用框架类型(int
有效,Int32
无效,等等)
现在,我试图重现这一点(VS2015中的C#6/Roslyn),但我没有得出相同的结论:
public enum TestEnum : UInt32
{
}
及
两者都是完全有效的。为什么会这样?还是什么改变了
编辑:
所以为了澄清问题,这是C#6中的一个变化,还没有被记录下来,而且很快就会被记录下来,你可以从git上的这个问题上读到,要么是新编译器的疏忽,要么是他们决定不再在语言中存在这种不一致性(?) 目前,似乎没有正式的规范,只有一个看起来不那么正式的git存储库,在那里工作正在进行:
目前看来,不为基础枚举类型使用别名应该是一个错误。该语言看起来与以前的官方规范相同。但是,由于编译器和规范似乎仍在进行中,很难说哪一种是正确的。现在使用C#6确实很奇怪。当前进行中的规范仍然列出了以下用于在中指定基的语法: 积分类型定义为: 根据该语言规范判断,使用静态类型标识符列表中未出现的其他基类型应该被解析器拒绝,并导致语法错误 考虑到情况并非如此,有两种可能性:要么故意更改解析器以接受非别名类型,要么解析器错误地接受这些类型 如果我们看一下Roslyn的实现,那么我们就能明白为什么规范中的这一要求没有得到执行。只是不检查它,而是解析任何类型:
baseList语法baseList=null;
if(this.CurrentToken.Kind==SyntaxKind.ColonToken)
{
var colon=this.EatToken(SyntaxKind.ColonToken);
var type=this.ParseType(false);
var tmpList=_pool.AllocateSeparated();
tmpList.Add(_syntaxFactory.SimpleBaseType(type));
baseList=\u syntaxFactory.baseList(冒号,tmpList);
_免费游泳池(tmpList);
}
在这一点上,它与标准没有太大区别。因此,任何类型限制都不会应用于语法级别,而是应用于语义级别,在语义级别上,可能已经对类型别名进行了计算
所以这似乎是一个bug:要么在规范中,要么在解析器中。考虑到规范仍在进行中,这可能会在以后得到解决。这是C#6中有意进行的语言更改,其规范仅以草稿形式发布。这是一个如此小的变化,我们总是忘记把它纳入规格
另请参见答案发布于2008年10月18日18:52,比C#6早几年!看起来他们已经修复了这个异常。这是一个新的编译器。@ChrisF gosh,我当时在groundschool,hahaI已经提交了文件。@svick谢谢你,sir,但是基础类型不需要扩展到框架类型吗?这似乎符合定义。@DanielA.White:如果您阅读了OP链接的问题,它提到规范指定基础类型必须与
integral_类型
产品相匹配,后者仅定义为C#内置关键字的列表,其他什么都没有。这一部分在“正在进行的工作”规范中是相同的。只要看看integral_类型
的定义,它听起来像是在任何地方使用的,它必须表示框架类型。integral_类型
定义本身只是一个单词列表(“sbyte”|“byte”|“short”|……
),因此,它只能引用神奇的C#特定关键字。我的理解是,在大多数地方,当谈论类型时,它指的是层次结构中更高的产品,它允许引用任意类或结构,因此System.Int32
等。枚举位是唯一直接指整型
产品的东西。
public enum TestEnum : UInt32
{
}
public enum MyEnum : uint
{
}
enum_base
: ':' integral_type
;
integral_type
: 'sbyte'
| 'byte'
| 'short'
| 'ushort'
| 'int'
| 'uint'
| 'long'
| 'ulong'
| 'char'
;
BaseListSyntax baseList = null;
if (this.CurrentToken.Kind == SyntaxKind.ColonToken)
{
var colon = this.EatToken(SyntaxKind.ColonToken);
var type = this.ParseType(false);
var tmpList = _pool.AllocateSeparated<BaseTypeSyntax>();
tmpList.Add(_syntaxFactory.SimpleBaseType(type));
baseList = _syntaxFactory.BaseList(colon, tmpList);
_pool.Free(tmpList);
}