编译器错误:"error CS0307:变量'int'不能与类型参数一起使用"

13

如果我有以下代码:

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) 时,我得到了编译时错误:

error CS0307: 变量 'int' 不能用作类型参数

同时我也得到了这些错误:

error CS0118: 'b' 是一个变量,但被用作类型
error CS0118: 'a' 是一个变量,但被用作类型

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


我不得不添加括号:Check((a<b), a>(flag ? c : b - 10));,但我不知道为什么,耸肩。编辑:同样,没有括号,>==也可以正常工作:Check(a==b, a>(flag ? c : b - 10));Check(a > b, a > (flag ? c : b - 10));。一定是某个与<相关的运算符? - Quantic
@Quantic Check(a<b,a>(flag?c:b-10)); 函数 a 带有泛型参数 <b,a> - L.B
@L.B 是的,没错,Check(a<b, a < (flag ? c : b - 10)); 运行良好(将 > 反转为 <,这样它就不再像一个通用方法了)。 - Quantic
@L.B 是的,但问题是为什么。听起来像是一个 bug? - Ivan Stoev
@IvanStoev 很难猜测编译器的作者为什么选择了这种方式... - L.B
显示剩余2条评论
1个回答

28

今天对我来说是个伟大的日子。我从未想过我会在野外看到这样的东西!我之前只在编译器测试中见过它。

考虑以下程序片段:

F(G<A,B>(7));
在C# 1.0中,这意味着“使用两个参数调用方法F:G<AB>(7)”。
但是C# 2.0添加了泛型。在C# 2.0中,这意味着“使用一个参数调用方法F。该参数是对泛型方法G<A, B>的调用,其具有一个参数7”。
这是一项重大变革。C#采用了一些启发式方法来确保符合此模式的旧程序继续工作,但不是所有程序都能如此。
C#正在解释你的程序。
Check(a < b, a > (flag ? c : b - 10));

作为一个带有一个参数的Check调用:带有一个参数的通用方法a<b, a>的调用。

对于您来说,解决方案很简单,就像您已经发现的那样:只需添加更多括号以分隔参数以用于Check

如果您想知道C#用于尝试区分何时泛型和何时不是的确切规则,则是:

如果符号序列可以解析为简单名称、成员访问或指针成员访问,这些都以类型参数列表结尾,则会检查紧跟在关闭>符号后面的符号。 如果它是以下之一:( ) ] } : ; , . ? == != | ^,则类型参数列表将保留为简单名称、成员访问或指针成员访问的一部分,并且任何其他可能的符号序列解析将被放弃。否则,即使没有其他可能的符号序列解析,类型参数列表也不被视为简单名称、成员访问或指针成员访问的一部分。请注意,在解析命名空间或类型名称中的类型参数列表时,不应用这些规则。

必须实现此类规则使得C#稍微有点难以解析,相信我。


8
这对我来说是个伟大的日子……这让我想起了类似这样的一句话:“如果你在一个寒冷多雨的日子看到一个走在街上微笑的人,那只能是预报员预报准确了” :) 只是开个玩笑,像往常一样,很棒的帖子! - Ivan Stoev

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接