共用方式為


空值合併賦值運算符

注意

本文是功能規格。 規格可作為功能的設計檔。 其中包含建議的規格變更,以及功能設計和開發期間所需的資訊。 這些文章會發佈,直到提議的規格變更完成並併併入目前的ECMA規格為止。

功能規格與已完成實作之間可能有一些差異。 這些差異是在的相關 語言設計會議(LDM)會議紀錄中擷取的。

您可以在 規格的文章中了解更多有關將功能規範納入 C# 語言標準的程序

冠軍問題:https://github.com/dotnet/csharplang/issues/34

總結

簡化常見的程式代碼撰寫模式,其中變數若為 Null,則會指派值。

在此提案中,我們將放寬 ?? 的類型要求,以允許在左側使用具有不受限制類型參數的表達式。

動機

通常可以看到類似這樣的程式碼

if (variable == null)
{
    variable = expression;
}

此提案會將不可多載的二進位運算元新增至執行此函式的語言。

至少有八個不同的社群提出了對此功能的要求。

詳細設計

我們會新增指派運算元的新形式

assignment_operator
    : '??='
    ;

它遵循複合賦值運算符的現有語意規則(§12.21.4),不同之處在於,如果左側非空值,則會省略賦值。 此功能的規則如下。

給定的 a ??= b,其中 Aa的類型,Bb的類型,如果 A0 為可為空的值類型,AA 的基礎類型:

  1. 如果 A 不存在或是不可為 Null 的實值類型,就會發生編譯時期錯誤。
  2. 如果 B 無法隱含轉換成 AA0(如果 A0 存在),則會發生編譯時期錯誤。
  3. 如果 A0 存在且 B 能隱含轉換成 A0,且 B 不是動態的,則 a ??= b 的類型是 A0a ??= b 會在運行時被評估為:
    var tmp = a.GetValueOrDefault();
    if (!a.HasValue) { tmp = b; a = tmp; }
    tmp
    
    唯一不同的是 a 只會被評估一次。
  4. 否則,a ??= b 的類型會是 Aa ??= b 會在執行時評估為 a ?? (a = b),但 a 只會評估一次。

為了放寬 ??的類型需求,我們會更新目前所述指定 a ?? b的規格,其中 Aa的類型:

  1. 如果 A 存在且不是可空類型或是引用類型,就會發生編譯時錯誤。

我們放寬這項要求至:

  1. 如果 A 存在且為不可為 Null 的實值型別,就會發生編譯時錯誤。

這可讓 Null 聯合運算符處理不受限制的類型參數,因為未限制的類型參數 T 存在,不是可為 Null 的類型,而且不是參考型別。

缺點

如同任何語言功能,我們必須質疑語言的額外複雜度是否在 C# 程序主體所提供的額外明確性中得到償還,而 C# 程式會受益於此功能。

替代方案

程序設計人員可以手動撰寫 (x = x ?? y)if (x == null) x = y;x ?? (x = y)

未解決的問題

  • [ ] 我們也應該支援 &&=||= 運算符嗎?

設計會議

沒有。