C# 将长值与int/long零常量进行比较
这是:C# 将长值与int/long零常量进行比较,c#,optimization,C#,Optimization,这是: if (myLongValue > 0) // 0 is displayed as int in Visual Studio tooltip 等于: if (myLongValue > 0L) 这是使用特殊的操作码吗?(类似于x86 asm中的JZ-jump if zero)。就IL而言,2是完全等效的。让我们以以下代码段为例: public static void Main(string[] args) { long myLongValue = long.Par
if (myLongValue > 0) // 0 is displayed as int in Visual Studio tooltip
等于:
if (myLongValue > 0L)
这是使用特殊的操作码吗?(类似于x86 asm中的JZ-jump if zero)。就IL而言,2是完全等效的。让我们以以下代码段为例:
public static void Main(string[] args)
{
long myLongValue = long.Parse("123");
if (myLongValue > 0)
{
Console.WriteLine("ok");
}
}
它被编译为以下IL(在发布模式下):
现在将if(myLongValue>0)
替换为if(myLongValue>0L)
,得到严格等效的IL
更理想的IL应该是这样,但不幸的是,我无法使编译器发出它:
.method public hidebysig static void Main(string[] args) cil managed
{
.entrypoint
.maxstack 2
.locals init (
[0] int64 myLongValue)
L_0000: ldstr "123"
L_0005: call int64 [mscorlib]System.Int64::Parse(string)
L_000a: stloc.0
L_000b: ldloc.0
L_000c: ldc.i8.0
L_000d: ble.s L_001a
L_0010: ldstr "ok"
L_0015: call void [mscorlib]System.Console::WriteLine(string)
L_001a: ret
}
这里我们不需要
conv.i8
指令,因为我们直接将提供的Int64类型的值作为Int64推送到求值堆栈上。在第一个示例中,运算符
的左侧是long
(System.Int64
),右侧是int
(System.Int32
)。由于C#规范没有定义带有该签名的
运算符的重载,因此我们必须检查某些转换是否适用于一个(或两个)参数(操作数)
存在从int
到long
的隐式转换。另一个方向的转换不是隐式的。因此,右侧通过加宽转换进行转换,并使用重载运算符>(长x,长y)
因为在本例中,右边的int
是编译时文本,编译器可以扩展常量,因此编译后两个示例之间没有差异。另一个答案演示了输出IL的外观
那么,如果你有:
ulong myULongValue = XXX;
if (myULongValue > 0)
...
一般来说,没有从int
(有符号)到ulong
(无符号)的隐式转换。但是,当int
是一个编译时常量(literal)碰巧是非负的时,确实存在转换。因此我上面的示例仍然有效(并产生与if(myULongValue>0ul)
)
但对于非常量int
,它必须失败:
ulong myULongValue = XXX;
int zero = 0; // not const
if (myULongValue > zero) // will NOT compile!
...
ulong myULongValue = XXX;
int zero = 0; // not const
if (myULongValue > zero) // will NOT compile!
...