编译器错误:“错误CS0307:变量’int’不能与类型参数一起使用”

如果我有以下代码:

private void Check(bool a, bool b) { } private void Check(int a, int b, int c, bool flag) { Check(a  (flag ? c : b - 10)); } 

我在调用Check(int, int)时遇到编译时错误:

错误CS0307:变量’int’不能与类型参数一起使用

我也得到这些错误:

错误CS0118:’b’是变量但是像类型一样使用
错误CS0118:’a’是变量但是像类型一样使用

为什么会出现这些错误? 代码有什么问题?

对我来说这是一个美好的一天。 我从没想过我会在野外看到其中的一个! 我在编译器测试用例中只见过这个。

考虑以下程序片段:

 F(G(7)); 

在C#1.0中,这意味着“使用两个参数调用方法F: G B>(7)B>(7)

但是C#2.0增加了generics。 在C#2.0中,这意味着“使用一个参数调用方法F。该参数是对generics方法G调用,带有一个参数,7”。

这是一个突破性的变化。 C#有一些启发式方法可以确保匹配此模式的旧程序继续工作,但并非所有程序都可以。

C#正在解释你的程序

 Check(a < b, a > (flag ? c : b - 10)); 

用一个参数调用Check :调用generics方法a带一个参数。

正如您所发现的那样,解决方案很简单:只需添加更多括号即可将参数分隔为Check。

如果您有兴趣知道C#使用的确切规则来判断它何时是通用的,何时不是,它是:

如果可以将一系列标记解析为以type-argument-list结尾的简单名称,成员访问或指针成员访问,则会检查紧跟在closing> token之后的标记。 如果是( ) ] } : ; , . ? == != | ^ ( ) ] } : ; , . ? == != | ^ ( ) ] } : ; , . ? == != | ^然后将type-argument-list保留为simple-name,member-access或pointer-member-access的一部分,并且丢弃令牌序列的任何其他可能的解析。 否则,type-argument-list不被认为是simple-name,member-access或pointer-member-access的一部分,即使没有其他可能的标记序列解析。 请注意,在解析namespace-or-type-name中的type-argument-list时,不会应用这些规则。

相信我,必须实现这样的规则使得C#解析起来有点棘手