如果我有以下代码:
private void Check(bool a, bool b)
{
}
private void Check(int a, int b, int c, bool flag)
{
Check(a < b, a > (flag ? c : b - 10));
}
我在调用Check(int, int)
时出现编译时错误:
错误CS0307:变量&#39; int&#39;不能与类型参数一起使用
我也遇到了这些错误:
错误CS0118:&#39; b&#39;是一个变量,但用作类型
错误CS0118:&#39; a&#39;是一个变量但是像类型一样使用
为什么会出现这些错误?代码有什么问题?
答案 0 :(得分:26)
对我来说这是美好的一天。我从没想过我会在野外看到其中的一个!我在编译器测试用例中只见过这个。
考虑以下程序片段:
F(G<A,B>(7));
在C#1.0中,这意味着&#34;使用两个参数调用方法F:G<A
和B>(7)
。
但是C#2.0增加了泛型。在C#2.0中,这意味着&#34;用一个参数调用方法F.该参数是对泛型方法G<A, B>
的调用,其中包含一个参数7&#34;。
这是一个突破性的变化。 C#有一些启发式方法可以确保符合此模式的旧程序继续工作,但并非所有程序都能正常工作。
C#正在解释你的程序
Check(a < b, a > (flag ? c : b - 10));
作为对Check
的一个参数的调用:使用一个参数调用泛型方法a<b, a>
。
正如您所发现的那样,解决方案很简单:只需添加更多括号即可将参数分隔为Check。
如果您有兴趣知道C#使用的确切规则,以确定它何时是通用的,何时不是,它是:
如果可以将一系列标记解析为以type-argument-list结尾的简单名称,成员访问或指针成员访问,则紧跟在结束之后的标记&gt;令牌被检查。如果它是
( ) ] } : ; , . ? == != | ^
之一,那么type-argument-list将作为simple-name,member-access或pointer-member-access的一部分保留,并且将丢弃令牌序列的任何其他可能的解析。否则,类型参数列表不被视为简单名称,成员访问或指针成员访问的一部分,即使没有其他可能的令牌序列解析。请注意,在解析namespace-or-type-name中的type-argument-list时,不应用这些规则。
必须实现这样的规则才能让C#解析有点棘手,相信我。