我很想知道为什么C#编译器只给我第二个if语句的错误信息。
enum Permissions : ulong
{
ViewListItems = 1L,
}
public void Method()
{
int mask = 138612833;
int compare = 32;
if (mask > 0 & (ulong)Permissions.ViewListItems > 32)
{
//Works
}
if (mask > 0 & (ulong)Permissions.ViewListItems > compare)
{
//Operator '>' cannot be applied to operands of type 'ulong' and 'int'
}
}
答案 0 :(得分:31)
我一直在尝试这个,使用ILSpy检查输出,这就是我发现的。
显然在你的第二种情况下这是一个错误 - 你无法比较ulong
和int
因为没有你可以强制转换的类型。对于ulong
,long
可能过大,而int
可能为负。
然而,在第一种情况下,编译器很聪明。它意识到const 1
> const 32
永远不会成立,并且根本不在编译输出中包含if
语句。 (它应该对无法访问的代码发出警告。)如果您定义并使用const int
而不是文字,或者即使您明确地转换文字(即(int)32
),也是一样的。
但是编译器是否成功地将ulong
与int
进行了比较,我们刚才说这是不可能的?
显然不是。那么 正在进行什么?
请尝试按以下方式执行操作。 (接受输入和写入输出,因此编译器不会编译任何东西。)
const int thirtytwo = 32;
static void Main(string[] args)
{
ulong x = ulong.Parse(Console.ReadLine());
bool gt = x > thirtytwo;
Console.WriteLine(gt);
}
这将编译,即使ulong
是变量,即使结果在编译时未知。看看ILSpy中的输出:
private static void Main(string[] args)
{
ulong x = ulong.Parse(Console.ReadLine());
bool gt = x > 32uL; /* Oh look, a ulong. */
Console.WriteLine(gt);
}
因此,编译器实际上将您的const int
视为ulong
。如果你做thirtytwo = -1
,代码就无法编译,即使我们知道gt
总是是真的。编译器本身无法将ulong
与int
进行比较。
另请注意,如果您使x
成为long
而不是ulong
,则编译器会生成32L
而不是32
作为整数,即使它没有。 (您可以在运行时比较int
和long
。)
这指向编译器在第一种情况下不将32
视为ulong
,因为它具有,仅仅因为可以匹配x
的类型。它可以节省运行时不必强制常量,这只是一种奖励,当强制不应该通过权利时。
答案 1 :(得分:21)
这不是CLR提供此错误消息,而是编译器。
在您的第一个示例中,编译器将32
视为ulong
(或者可隐式转换为ulong
的类型,例如uint
),而在第二个示例中,您明确表示int
将类型声明为>
。接受ulong
和int
的{{1}}运算符没有重载,因此会出现编译错误。
答案 2 :(得分:3)