[英]The behavior of null-coalescing assignment operator
我只是想知道??=運算符如何在后台運行。 我有兩個問題。
考慮下面的例子,
string name = "John";
name ??= "George";
1)是否等於name = name ?? "George";
name = name ?? "George";
2)它是這樣工作的嗎,
if (name == null) {
name = "George";
}
或者
if (name == null) {
name = "George";
}
else {
name = name;
}
它將被評估為:
string text = "John";
if (text == null)
{
text = "George";
}
您可以使用sharplab
查看實際發生的情況:
更多信息: https : //stackoverflow.com/a/59300172/2946329
基於文檔:
C# 8.0 引入了空合並賦值運算符 ??=。 僅當左側操作數的計算結果為 null 時,您才可以使用 ??= 運算符將其右側操作數的值分配給其左側操作數。
根據文檔
空合並賦值運算符
??=
僅當左側操作數的計算結果為null
時才將其右側操作數的值分配給其左側操作數。 如果左側操作數的計算結果為非空,則??=
運算符不會計算其右側操作數。
在您的代碼示例中,它不會被評估,因為name
不為null
string name = "John";
name ??= "George";
如果你寫這樣的東西它會起作用
string name = null;
name ??= "George";
名稱值為George
。 擴展變體是
if (name is null) //or name == null
{
name = "George";
}
空合並運算符
??
如果左操作數不為null
,則返回其值; 否則,它評估右側操作數並返回結果。
在此示例中name = name ?? "George"
name = name ?? "George"
只有在 name 之前為null
值時,結果才會是George
。 我您的樣品name = name ?? "George";
name = name ?? "George";
等於name ??= "George";
在返回結果方面。 但是在這兩種情況下,只有在分配之前原始name
為null
時,您才能獲得George
值。 您也可以參考語言規范了解詳情
您可以使用https://sharplab.io/來測試差異。 ??=
和??
之間的區別非常小,一旦代碼經過 JIT 編譯,它實際上就消失了。
簡而言之 :
if (text == null){
text = "George";
}
SharpLab 示例
這個例子的代碼:
public void M1() {
string name = "John";
name ??= "George";
Console.WriteLine(name);
}
public void M2() {
string name = "John";
name = name ?? "George";
Console.WriteLine(name);
}
生成這個中間 C# 代碼,它顯示了真正的區別:
public void M1()
{
string text = "John";
if (text == null)
{
text = "George";
}
Console.WriteLine(text);
}
public void M2()
{
string text = "John";
text = (text ?? "George");
Console.WriteLine(text);
}
除了dup
(復制)和pop
操作外,IL 幾乎相同。 你會認為??
這有點慢:
IL_0000: nop
IL_0001: ldstr "John"
IL_0006: stloc.0
IL_0007: ldloc.0
IL_0008: brtrue.s IL_0010
IL_000a: ldstr "George"
IL_000f: stloc.0
IL_0010: ldloc.0
IL_0011: call void [System.Console]System.Console::WriteLine(string)
IL_0016: nop
IL_0017: ret
對比
IL_0000: nop
IL_0001: ldstr "John"
IL_0006: stloc.0
IL_0007: ldloc.0
*** IL_0008: dup
IL_0009: brtrue.s IL_0011
*** IL_000b: pop
IL_000c: ldstr "George"
IL_0011: stloc.0
IL_0012: ldloc.0
IL_0013: call void [System.Console]System.Console::WriteLine(string)
IL_0018: nop
IL_0019: ret
但是發布模式下的程序集是相同的:
C.M1()
L0000: mov ecx, [0x1a58b46c]
L0006: test ecx, ecx
L0008: jnz L0010
L000a: mov ecx, [0x1a58b470]
L0010: call System.Console.WriteLine(System.String)
L0015: ret
C.M2()
L0000: mov ecx, [0x1a58b46c]
L0006: test ecx, ecx
L0008: jnz L0010
L000a: mov ecx, [0x1a58b470]
L0010: call System.Console.WriteLine(System.String)
L0015: ret
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.