這是長期價值:比較INT /長恆爲零
if (myLongValue > 0) // 0 is displayed as int in Visual Studio tooltip
等於:
if (myLongValue > 0L)
而且這是使用特殊的操作碼? (類似於JZ - 如果在x86 asm中爲0則跳轉)。
這是長期價值:比較INT /長恆爲零
if (myLongValue > 0) // 0 is displayed as int in Visual Studio tooltip
等於:
if (myLongValue > 0L)
而且這是使用特殊的操作碼? (類似於JZ - 如果在x86 asm中爲0則跳轉)。
2在IL方面完全相同。讓我們以例如下面的代碼片段:
public static void Main(string[] args)
{
long myLongValue = long.Parse("123");
if (myLongValue > 0)
{
Console.WriteLine("ok");
}
}
它被編譯到下面白細胞介素(在Release模式):
.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.i4.0
L_000d: conv.i8
L_000e: ble.s L_001a
L_0010: ldstr "ok"
L_0015: call void [mscorlib]System.Console::WriteLine(string)
L_001a: ret
}
現在更換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
的轉換。其他方向的轉換不是隱含的。因此,右側將通過加寬轉換進行轉換,並使用過載operator >(long x, long y)
。
因爲在這種情況下,右側int
是一個編譯時文字,編譯器可以做到不斷的拉大,所以有編譯後的兩個實例之間沒有什麼區別。另一個答案已經證明了輸出IL的樣子。
所以,如果不是你有什麼:
ulong myULongValue = XXX;
if (myULongValue > 0)
...
一般情況下,有從int
沒有隱轉換(簽名)ulong
(無符號)。但是,當int
是一個非負的編譯時常量(文字)時,確實存在轉換。所以我上面的例子仍然有效(和if (myULongValue > 0ul)
一樣)。
但對於非恆定int
,它有失敗:
ulong myULongValue = XXX;
int zero = 0; // not const
if (myULongValue > zero) // will NOT compile!
...
感謝豐富的答案:) – zgnilec