簡體   English   中英

空合並賦值運算符的行為

[英]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://sharplab.io/#v2:CYLg1APgAgTAjAWAFBQMwAJboMLoN7LpGYZQAs6AsgBQCU+hxTUcADOgHYCGAtgKboAvOgBEAKQD2ACw4iA3Mm790AfhXCRAcT4SATgHM+80xQC

更多信息: 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"; 在返回結果方面。 但是在這兩種情況下,只有在分配之前原始namenull時,您才能獲得George值。 您也可以參考語言規范了解詳情

您可以使用https://sharplab.io/來測試差異。 ??=??之間的區別非常小,一旦代碼經過 JIT 編譯,它實際上就消失了。

簡而言之 :

  1. 一旦代碼被編譯成程序集,它是一樣的。
  2. 相當於:
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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM