?? 和 ??= 运算符 - Null 合并操作符

如果左作数不是??,则 null 合并运算符null返回其左作数的值;否则,它将计算右侧作数并返回其结果。 如果左侧操作数的计算结果为非 null,则 ?? 运算符不会计算其右侧操作数。 仅当左操作数的计算结果为 ??= 时,Null 合并赋值运算符 null 才会将其右操作数的值赋值给其左操作数。 如果左侧操作数的计算结果为非 null,则 ??= 运算符不会计算其右侧操作数。

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

Console.WriteLine((numbers is null)); // expected: true
// if numbers is null, initialize it. Then, add 5 to numbers
(numbers ??= new List<int>()).Add(5);
Console.WriteLine(string.Join(" ", numbers));  // output: 5
Console.WriteLine((numbers is null)); // expected: false        


Console.WriteLine((a is null)); // expected: true
Console.WriteLine((a ?? 3)); // expected: 3 since a is still null 
// if a is null then assign 0 to a and add a to the list
numbers.Add(a ??= 0);
Console.WriteLine((a is null)); // expected: false        
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-conditional 运算符?.?[]的表达式中,可以使用??运算符提供一个备选表达式,以便在 null-conditional 运算的结果为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 的类型的值为 Nullable<T>.GetValueOrDefault() 时要使用的值应为基础值类型的默认值,请使用 null 方法。

  • 可以使用 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 合并运算符部分。

有关 ??= 操作符的详细信息,请参阅 功能建议说明

另请参阅