嵌套通用语法歧义>>

Ole*_*lik 10 c# lexer nested-generics

显然,C#和C++一样容易受到'>>'lexer困境的影响.

这个C#代码非常有效,它编译并运行得很好:

var List = new Dummy("List");
var Nullable = new Dummy("Nullable");
var Guid = new Dummy("Guid");

var x = List<Nullable<Guid>> 10;
var y =  List<Nullable<Guid>> .Equals(10,20);
Run Code Online (Sandbox Code Playgroud)

您必须为上面的Dummy类重载'<'和'>>'运算符.

但编译器设法猜测在'x'情况下,意思是使用List,Nullable和Guid局部变量.在'y'的情况下,它突然决定将它们视为众所周知的类型的名称.

以下是另一个例子的更详细描述:http: //mihailik.blogspot.co.uk/2012/05/nested-generics-c-can-be-stinky.html

问题是:C#编译器如何将'a <b <c >>'解析为算术表达式或泛型类型/方法?

当然,它不会尝试在程序文本上多次"运行",直到它成功,或者它是否成功?这需要无限前瞻,而且非常复杂.

Ole*_*lik 5

我已经被引导到C#语言规范中的7.6.4.2段:

http://download.microsoft.com/download/0/B/D/0BDA894F-2CCD-4C2C-B5A7-4EB1171962E5/CSharp%20Language%20Specification.htm

简单名称(第7.6.2节)和成员访问(第7.6.4节)的产生可能会导致表达式语法含糊不清.

...

如果一个标记序列可以作为简单名称(第7.6.2节),成员访问(第7.6.4节)或以类型结尾的指针成员访问(第18.5.2节)进行解析(在上下文中) -argument-list(§4.4.1),检查紧跟在closing>令牌之后的令牌.如果它是其中之一

()]}:; ,.?==!= | ^

然后将type-argument-list保留为simple-name,member-access或pointer-member-access的一部分,并且丢弃令牌序列的任何其他可能的解析.否则,类型参数列表不被视为简单名称,成员访问或指针成员访问的一部分,即使没有其他可能的令牌序列解析.请注意,在解析namespace-or-type-name(§3.8)中的type-argument-list时,不应用这些规则.

因此,当涉及到type-argument-list时,确实可能出现歧义,并且通过提前查看一个令牌,他们有一种廉价的方法来解决它.

它仍然是一个未绑定的未来,因为'>>'和跟随令牌之间可能存在一个兆字节的评论,但至少规则或多或少是清楚的.最重要的是,不需要推测深度解析.