?? 和??= 運算子 - Null 聯合運算子

如果 Null 聯合運算子 ?? 不是 null,會傳回其左方運算元的值;否則它會評估右方運算元,並傳回其結果。 如果左側運算元評估為非 Null,則 ?? 運算子不會評估右側運算元。 Null 聯合指派運算子只有在左側運算元 ??= 評估 null 為 時,才會將右運算元的值指派給其左側運算元。 如果左側運算元評估為非 Null,則 ??= 運算子不會評估右側運算元。

List<int> numbers = null;
int? a = null;

(numbers ??= new List<int>()).Add(5);
Console.WriteLine(string.Join(" ", numbers));  // output: 5

numbers.Add(a ??= 0);
Console.WriteLine(string.Join(" ", numbers));  // output: 5 0
Console.WriteLine(a);  // output: 0

運算子的 ??= 左側運算元必須是變數、 屬性索引子 元素。

??= 運算子的左側運算元 ?? 類型不能是不可為 Null 的實值型別。 特別是,您可以使用 Null 聯合運算子搭配未受限制的類型參數:

private static void Display<T>(T a, T backup)
{
    Console.WriteLine(a ?? backup);
}

Null 聯合運算子是右關聯運算子。 也就是說,表單的運算式

a ?? b ?? c
d ??= e ??= f

評估為

a ?? (b ?? c)
d ??= (e ??= f)

範例

????= 運算子在下列案例中很有用:

  • 在具有Null 條件運算子 ?.?[]的運算式中,您可以使用 ?? 運算子來提供替代運算式,以在具有 Null 條件式運算的運算式結果為 null 時進行評估:

    double SumNumbers(List<double[]> setsOfNumbers, int indexOfSetToSum)
    {
        return setsOfNumbers?[indexOfSetToSum]?.Sum() ?? double.NaN;
    }
    
    var sum = SumNumbers(null, 0);
    Console.WriteLine(sum);  // output: NaN
    
  • 當您使用 可為 Null 的實值型 別,而且需要提供基礎實值型別的值時,請使用 ?? 運算子來指定要提供的值,以防可為 Null 的型別值為 null

    int? a = null;
    int b = a ?? -1;
    Console.WriteLine(b);  // output: -1
    

    如果可為 Null 型別的值為 null 時要使用的值為基礎實值型別的預設值,請使用 Nullable<T>.GetValueOrDefault() 方法。

  • 您可以使用throw 運算式作為運算子的 ?? 右運算元,讓引數檢查程式碼更簡潔:

    public string Name
    {
        get => name;
        set => name = value ?? throw new ArgumentNullException(nameof(value), "Name cannot be null");
    }
    

    上述範例中也會示範如何使用運算式主體成員定義屬性。

  • 您可以使用 ??= 運算子來取代表單的程式碼

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

    取代為下列程式碼:

    variable ??= expression;
    

運算子是否可多載

運算子 ????= 無法多載。

C# 語言規格

如需 運算子的詳細資訊 ?? ,請參閱C# 語言規格Null 聯合運算子一節。

如需運算子的詳細資訊 ??= ,請參閱 功能提案附注

另請參閱