26

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

3 回答 3

32

我一直在对此进行试验,使用 ILSpy 来检查输出,这就是我发现的。

显然,在您的第二种情况下,这是一个错误-您无法比较 aulong和 anint因为没有可以强制两者的类型。Aulong可能对于 a 来说太大了long,并且 anint可能是负数。

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

但是编译器不是成功地将 aulong与a 进行比较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. 如果你 make thirtytwo = -1,代码将无法编译,即使我们知道这gt永远是正确的。编译器本身无法将 aulong与 a 进行比较int

另请注意,如果您使用xalong而不是 a ulong,编译器会生成32L而不是32整数,即使它不是必须的。(您可以在运行时比较 anint和 a long。)

这表明编译器在第一种情况下没有将32其视为 a ,因为它必须这样做,仅仅是因为它可以匹配 的类型。它使运行时不必强制常量,这只是当强制应该不可能的时候的奖励。ulongx

于 2012-06-18T15:47:07.943 回答
21

给出此错误消息的不是 CLR,而是编译器。

在您的第一个示例中,编译器将32其视为ulong(或可隐式转换为ulongeg的类型uint),而在您的第二个示例中,您已将类型显式声明为int. >接受 anulong和 an的运算符没有重载,int因此会出现编译器错误。

于 2012-06-18T15:48:24.543 回答
3

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

if (mask > 0 & (ulong)Permissions.ViewListItems > Convert.ToUInt64(compare))
{
}
于 2012-06-18T15:57:24.773 回答