C# 嵌套泛型语法歧义>&燃气轮机;

C# 嵌套泛型语法歧义>&燃气轮机;,c#,lexer,nested-generics,C#,Lexer,Nested Generics,显然,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);

显然,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);
var List=新的虚拟(“列表”);
var Nullable=新虚拟(“Nullable”);
var Guid=新虚拟(“Guid”);
var x=列表10;
var y=列表。等于(10,20);
您必须为上面的虚拟类重载'>'运算符

但是编译器设法猜测,在“x”的情况下,其含义是使用List、Nullable和Guid局部变量。在“y”的情况下,它突然决定将它们作为知名类型的名称对待

下面是另一个示例的更详细描述:

问题是:C#编译器如何将“a”解析为算术表达式或泛型类型/方法


当然,在程序成功之前,它不会尝试对程序的文本进行多次“检查”,或者是吗?这需要无限的前瞻性,也需要一个非常复杂的过程。

编辑:我坚持认为没有歧义: 在您的示例中,没有任何歧义。这永远不能作为
列表进行评估。上下文(额外的10)向编译器展示了如何解释它

var x = List<Nullable<Guid>> 10;
很明显,10是一个字面意思。如果你继续学习语法,你会发现:10是一个*字面值,所以它是*主无数组创建表达式,它是*主表达式,它是*一元表达式,它是*乘法表达式,它是*加法表达式。如果在*>>的右侧查找加法表达式,您会发现它必须是*shift表达式,因此*>>的左侧必须解释为*additional表达式,依此类推

如果你能找到一种不同的方法来使用语法,并且对同一个表达式得到不同的结果,那么,我必须同意你的观点,但让我不同意

最后:

  • 这对人类来说是非常令人困惑的
  • 对于编译器来说是绝对清晰和明确的
因为:

  • 我们人类从我们熟悉的整个文本片段中识别模式,如
    List
    ,并按照我们的意愿解释它们
  • 编译器不像我们那样解释代码,使用熟悉的片段,如
    List
    。他们将整个表达式与语言语法相匹配

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

简单名称(§7.6.2)和成员访问(§7.6.4)的结果可能会在表达式的语法中产生歧义

如果可以(在上下文中)将令牌序列解析为以类型参数列表(§4.4.1)结尾的简单名称(§7.6.2)、成员访问(§7.6.4)或指针成员访问(§18.5.2),则将检查紧跟在closing>令牌之后的令牌。如果是其中一个

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

然后,类型参数列表将作为简单名称、成员访问或指针成员访问的一部分保留,并放弃对令牌序列的任何其他可能的解析。否则,类型参数列表不会被视为简单名称、成员访问或指针成员访问的一部分,即使没有其他可能的令牌序列解析。请注意,这些规则在解析命名空间或类型名称中的类型参数列表时不适用(§3.8)

所以,当涉及类型参数列表时,确实可能会出现歧义,而且他们已经找到了一种廉价的方法来解决它,只需向前看一个标记


这仍然是一个未绑定的前瞻,因为在“>>”和下面的标记之间可能有一个兆字节的注释,但至少规则或多或少是清楚的。最重要的是,不需要进行推测性的深度解析。

“选择一个意思而不是另一个?”。。。什么意思?这里只有一个明确的含义。。。。唯一缺乏清晰性的是变量名的选择。“a”的含义严重依赖于上下文。编程语言允许这样做是不寻常的。实际上,主要的问题是编译器如何决定它是算术移位还是泛型类型规范的一部分。如果你疯狂到超负荷“>”,你应该期待得到什么。这让我想起;)这并不是说我疯狂到使用该语言的合法功能,而是说编译器如何解决这个谜。你和我都看了语法并应用了常识,但是编译器需要一个明确的规则,它没有常识。我说它编译是因为它有常识。正是这段代码,我在VisualStudio2010中编译并运行了它。我知道这听起来不太可能,这就是为什么这是一件令人不安的事情。虚拟类就在那个链接后面,为了简洁起见,我跳过了它给出了指向Nullable的错误“Struct name此时无效”。我真的很想看到它工作,但我不能。你能展示整个代码,包括“使用”部分吗?我在你的博客里也看不到。嗯。。。太奇怪了。是雷沙珀发现了这个错误。但是VS编译它。@OlegMihailik:我很抱歉认为它无法编译。挑战你去做。事实上,Resharper也会误解代码并显示错误,但VS会编译代码。(也是VS 2008)。没问题,如果我们没有犯错误,我们就不需要StackOverflow:-)
var x = List<Guid?> 10;
var y =  List<Nullable<Guid>> .Equals(10,20);
var x = List<Nullable<Guid>> 10;