解析器前沿的泛型和挑战

Bac*_*ave 9 c# generics

如果你有:

F(G<A,B>(4));
Run Code Online (Sandbox Code Playgroud)

这是否意味着用户想要通过比较G和A以及B和常数4得到的2个参数来调用方法F.

或者它是否意味着使用类型参数A和B以及参数4来调用泛型方法G的结果?

p.s*_*w.g 7

所以我试了一下才确定.事实证明这很好用:

void F(int x) { }
int G<T, U>(int x) { return x; }

class A { }
class B { }

void Main()
{
    F(G<A,B>(4));
}
Run Code Online (Sandbox Code Playgroud)

但是这会产生许多编译错误:

void F(bool x, bool y) { }

void Main()
{
    int G = 0, A = 1, B = 2;
    F(G<A,B>(4));
}
Run Code Online (Sandbox Code Playgroud)

找不到类型或命名空间名称"A"(按F4添加using指令或程序集引用)

找不到类型或命名空间名称"B"(您是否缺少using指令或程序集引用?)

变量'G'不是通用方法.如果您打算使用表达式列表,请在<expression周围使用括号.

所以答案是表达式F(G<A,B>(4))被解释为泛型函数调用.有任意数量的方式来强制编译器把它当作两个参数一个函数调用:F(G<A,B>4),F((G)<A,B>(4)),或者F(G>A,B>(4)),只是仅举几例.


Mik*_*ray 6

您应该阅读C#规范的7.6.4.2,该规范处理语法歧义并且几乎逐字地讨论这个例子.报价:

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

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

然后将type-argument-list保留为simple-name,member-access或pointer-member-access的一部分,并且丢弃令牌序列的任何其他可能的解析.

这里G是一个简单的名称,问题是是否<A,B>要将type-argument-list解释为此简单名称的一部分.

有一个(>,使该片段G<A,B>是一种方法的简单名称.该方法是一种通用的方法用类型参数AB和的4参数F因此是具有单个参数的方法.

需要注意的一件有趣的事情是,如果解析失败,编译器不会考虑任何替代方案.从pswg的答案中可以看出,即使唯一有效的解释是一个F带有两个参数的方法,也不考虑它.