您可能會問錯的問題。您不會選擇使用其中一種,主要是因爲效率(儘管它可能是次要問題),但是由於效用。
真的,你應該比較??
到?:
而不是if
,因爲它們有不同的目的。是的,他們都是某種形式的「有條件的」善,但關鍵是??
和?:
評估爲一個值,而if
沒有,因此他們經常有不同的用途。
例如,下面的代碼:
Console.WriteLine("The order} is for {1} product",
orderId, productId ?? "every");
將是笨重與if
寫:
if (productId == null)
{
Console.WriteLine("The order {0} is for every product",
orderId);
}
else
{
Console.WriteLine("The order {0} is for {1} product",
orderId, productId);
}
是的,你可能會凝結成一個,但隨後你就會有一個臨時變量等:
if (productId == null)
{
productId = "every";
}
Console.WriteLine("The order {0} is for {1} product",
orderId, productId);
因此,真的,你不應該比較這兩個,因爲它們的指針如果參數是null
,則??
的t值將計算爲一個值,而if
的值則執行不同的路徑(不直接生成值。
所以,一個更好的問題可能是,爲什麼不是這個:
Console.WriteLine("The order {0} is for {1} product",
orderId, productId == null ? "every" : productId);
這是大致相同(均爲評估的值),並沒有那麼多的流量控制。
因此,我們來看看其中的差異。讓我們寫這樣的代碼三種方式:
// Way 1 with if
string foo = null;
string folder = foo;
if (folder == null)
{
folder = "bar";
}
// Way 2 with ? :
string foo2 = null;
var folder2 = foo2 != null ? foo2 : "bar";
// Way 3 with ??
string foo3 = null;
var folder3 = foo3 ?? "bar";
爲IF,我們得到以下的IL:
IL_0001: ldnull
IL_0002: stloc.0
IL_0003: ldloc.0
IL_0004: ldnull
IL_0005: ceq
IL_0007: ldc.i4.0
IL_0008: ceq
IL_000A: stloc.1
IL_000B: ldloc.1
IL_000C: brtrue.s IL_0016
IL_000E: nop
IL_000F: ldstr "bar"
IL_0014: stloc.0
對於條件(:)我們得到以下IL:
IL_0001: ldnull
IL_0002: stloc.0
IL_0003: ldloc.0
IL_0004: brtrue.s IL_000D
IL_0006: ldstr "bar"
IL_000B: br.s IL_000E
IL_000D: ldloc.0
IL_000E: nop
IL_000F: stloc.1
對於無漏白(??)我們得到這個IL:
IL_0001: ldnull
IL_0002: stloc.0
IL_0003: ldloc.0
IL_0004: dup
IL_0005: brtrue.s IL_000D
IL_0007: pop
IL_0008: ldstr "bar"
IL_000D: stloc.1
請注意每個後續步驟如何更簡單? if
是較大的IL,因爲它需要分支邏輯來處理單獨的語句。 ?:
較小,因爲它只是計算一個值(不支持其他語句),但仍然需要加載操作數以與(null
)進行比較。
的??
是最簡單的,因爲那裏是比較null
(VS裝載null
和比較它的IL指令。
SO這一切說,你說一個非常小不管怎樣,這可能會或可能不會影響性能。無論如何,這將有很大的差別,與程序(數學,數據庫,網絡等)中的更多密集工作相比,幾乎沒有什麼區別。因此,我會建議選擇那個大多數是可讀的,並且只有在通過分析發現您當前的方法不足且存在瓶頸時纔會進行優化。
對我來說,使用?:
或??
的真正原因是當您希望最終結果是一個值時。也就是說,任何時候你會忍不住寫:
if (someCondition)
x = value1;
else
x = value2;
然後我會使用條件(?:
),因爲這是它是一個偉大的簡寫。 x
得到一個或基於此條件下,其他值...
然後我會走得更遠一個與??
和說的一樣是真的,你要分配一個值基礎上,null
-ness的變量一個身份識別者。
所以if
是偉大的流量控制,但如果你只是返回兩個值中的一個或分配基於一個條件的兩個值中的一個,我會使用?:
或??
適當。
最後記住這些東西是如何蓋(IL和相關的性能)下執行受與.NET Framework的每個修訂改變(因爲我現在寫這個權利,他們都如此接近可以忽略不計)。
因此,明天可能會更快的可能不會更快。再說一次,我只是說一個最合適的,你發現最可讀的。
UPDATE
順便說一句,對於真正的癡迷,我比較了每個代碼樣本的10,000,000迭代以上,而這裏的執行每個的總時間。貌似??
是最快的,對我來說這個數字也只是所以接近是幾乎無關緊要......
10,000,000 iterations of:
?: took: 489 ms, 4.89E-06 ms/item.
?? took: 458 ms, 4.58E-06 ms/item.
if took: 641 ms, 6.41E-06 ms/item.
它更像是語法糖.. – Amitd
如果您是關注運行時,C#可能不你最好的選擇。 –
從技術上講,你應該把'??'與'?'比較:''不要'if'作爲'?:'比'if'更接近'''更合乎邏輯。 –