我很想知道为什么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'
}
}
Run Code Online (Sandbox Code Playgroud)
Raw*_*ing 32
我一直在试验这个,使用ILSpy检查输出,这就是我发现的.
显然,在你的第二种情况下,这是一个错误 - 你无法比较a ulong和a ,int因为没有你可以强制执行的类型.A ulong可能对a来说太大了long,而且int可能是负面的.
但是,在第一种情况下,编译器很聪明.它意识到const 1> const 32永远不会成立,并且根本不包括if编译输出中的语句.(它应该对无法访问的代码发出警告.)如果你定义和使用一个const int而不是一个文字,或者即使你明确地转换文字(即(int)32),它也是一样的.
但那么编译器是否成功地将a ulong与a进行比较int,我们刚才说这是不可能的?
显然不是.那是怎么回事?
请尝试沿着以下方向做某事.(输入和写入输出,因此编译器不会编译任何东西.)
const int thirtytwo = 32;
static void Main(string[] args)
{
ulong x = ulong.Parse(Console.ReadLine());
bool gt = x > thirtytwo;
Console.WriteLine(gt);
}
Run Code Online (Sandbox Code Playgroud)
这将编译,即使它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);
}
Run Code Online (Sandbox Code Playgroud)
所以,编译器实际上将你const int视为一个ulong.如果你做了thirtytwo = -1,代码就无法编译,即使我们知道这gt将永远是真的.编译器本身无法将a与a ulong进行比较int.
还要注意的是,如果你做x一个long,而不是一个ulong,编译器生成32L,而不是32一个整数,尽管它不具备对.(您可以在运行时比较a int和a long.)
这指向编译器在第一种情况下不处理32为ulong因为它必须,仅仅因为它可以匹配的类型x.它可以节省运行时不必强制常量,这只是一种奖励,当强制不应该通过权利.
Ric*_*lly 21
它不是CLR给出这个错误消息它是编译器.
在你的第一个例子中,编译器将32作为ulong(或类型的隐式转换为ulong如uint),而在第二个例子中,你已经明确声明的类型为int.>接收a ulong和a 的运算符没有重载,int因此会出现编译错误.