如果你有:
F(G<A,B>(4));
这是否意味着用户想要通过比较G和A以及B和常数4来生成2个参数来调用方法F?
或者它是否意味着使用类型参数A和B以及参数4调用泛型方法G的结果调用F?
答案 0 :(得分:7)
所以我试了一下才确定。事实证明这很好用:
void F(int x) { }
int G<T, U>(int x) { return x; }
class A { }
class B { }
void Main()
{
F(G<A,B>(4));
}
但这会产生许多编译错误:
void F(bool x, bool y) { }
void Main()
{
int G = 0, A = 1, B = 2;
F(G<A,B>(4));
}
找不到类型或命名空间名称“A”(按F4添加using指令或程序集引用)
找不到类型或命名空间名称“B”(您是否缺少using指令或程序集引用?)
变量'G'不是通用方法。如果您打算使用表达式列表,请在&lt;周围使用括号。表达
所以答案是表达式F(G<A,B>(4))
被解释为泛型函数调用。有许多方法可以强制编译器将其视为两个参数的单个函数调用:F(G<A,B>4)
,F((G)<A,B>(4))
或F(G>A,B>(4))
,仅举几例。
答案 1 :(得分:6)
你应该阅读C#规范的7.6.4.2,该规范处理语法歧义并且几乎逐字地讨论这个例子。引用:
如果一个标记序列可以解析(在上下文中)作为简单名称(第7.6.2节),成员访问(第7.6.4节)或指针成员访问(第18.5.2节)结束使用type-argument-list(§4.4.1),将检查紧跟在结束
之一>
标记之后的标记。如果是()]}:; ,。 ? ==!= | ^
然后将type-argument-list保留为simple-name,member-access或pointer-member-access的一部分,并且丢弃令牌序列的任何其他可能的解析。
这里,G
是一个简单的名称,问题是<A,B>
是否被解释为类型参数列表,作为这个简单名称的一部分。
(
后面有>
,因此片段G<A,B>
是方法的简单名称。该方法是一个泛型方法,类型参数为A
和B
,参数为4. F
因此是一个带有单个参数的方法。
需要注意的一件有趣的事情是,如果解析失败,编译器不会考虑任何替代方案。正如您在p.s.w.g.的答案中所看到的,即使唯一有效的解释是F
是一个带有两个参数的方法,也不会考虑它。