运营商">"不能用于类型' ulong'和' int'

时间:2012-06-18 15:44:29

标签: c# .net

我很想知道为什么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'
    }
}

3 个答案:

答案 0 :(得分:31)

我一直在尝试这个,使用ILSpy检查输出,这就是我发现的。

显然在你的第二种情况下这是一个错误 - 你无法比较ulongint因为没有你可以强制转换的类型。对于ulonglong可能过大,而int可能为负。

然而,在第一种情况下,编译器很聪明。它意识到const 1> const 32永远不会成立,并且根本不在编译输出中包含if语句。 (它应该对无法访问的代码发出警告。)如果您定义并使用const int而不是文字,或者即使您明确地转换文字(即(int)32),也是一样的。

但是编译器是否成功地将ulongint进行了比较,我们刚才说这是不可能的?

显然不是。那么 正在进行什么?

请尝试按以下方式执行操作。 (接受输入和写入输出,因此编译器不会编译任何东西。)

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 总是是真的。编译器本身无法将ulongint进行比较。

另请注意,如果您使x成为long而不是ulong,则编译器会生成32L而不是32作为整数,即使它没有。 (您可以在运行时比较intlong。)

这指向编译器在第一种情况下不将32视为ulong,因为它具有,仅仅因为可以匹配x的类型。它可以节省运行时不必强制常量,这只是一种奖励,当强制不应该通过权利时。

答案 1 :(得分:21)

这不是CLR提供此错误消息,而是编译器。

在您的第一个示例中,编译器将32视为ulong(或者可隐式转换为ulong的类型,例如uint),而在第二个示例中,您明确表示int将类型声明为>。接受ulongint的{​​{1}}运算符没有重载,因此会出现编译错误。

答案 2 :(得分:3)

rich.okelly和rawling的答案是正确的,为什么你不能直接比较它们。您可以使用Convert类的ToUInt64方法来推广int。

if (mask > 0 & (ulong)Permissions.ViewListItems > Convert.ToUInt64(compare))
{
}