?? 和??= 運算子 (C# 參考)

如果 Null 聯合運算子 ?? 不是 null,會傳回其左方運算元的值;否則它會評估右方運算元,並傳回其結果。 如果左側運算元評估為非 Null,則 ?? 運算子不會評估右側運算元。

在 C# 8.0 和更新版本中,只有在左側運算元評估 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

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

在 C# 7.3 和更早版本中,運算子左側操作 ?? 數的類型必須是 參考型別可為 Null 的實值型別。 從 C# 8.0 開始,該需求會取代為下列專案:和 ??= 運算子的左側運算元 ?? 類型不能是不可為 Null 的實值型別。 特別是,從 C# 8.0 開始,您可以使用 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() 方法。

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

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

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

  • 從 C# 8.0 開始,您可以使用 ??= 運算子來取代表單的程式碼

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

    取代為下列程式碼:

    variable ??= expression;
    

運算子是否可多載

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

C# 語言規格

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

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

另請參閱