?? 和??= 運算子 (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 聯合運算子一節。

如需操作員的詳細資訊 ??= ,請參閱 功能提案注意事項

另請參閱