NULL 合并分配null coalescing assignment

  • [x] 建议[x] Proposed
  • [x] 原型:已完成[x] Prototype: Completed
  • [x] 实现:已完成[x] Implementation: Completed
  • [x] 规范:以下[x] Specification: Below

总结Summary

简化了一个常见的编码模式,其中如果变量为 null,则为该变量分配一个值。Simplifies a common coding pattern where a variable is assigned a value if it is null.

作为此建议的一部分,我们还将放宽的类型要求, ?? 以允许类型为不受约束的类型参数的表达式在左侧使用。As part of this proposal, we will also loosen the type requirements on ?? to allow an expression whose type is an unconstrained type parameter to be used on the left-hand side.

动机Motivation

通常会看到窗体的代码It is common to see code of the form

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

此建议向执行此函数的语言添加不可重载的二元运算符。This proposal adds a non-overloadable binary operator to the language that performs this function.

此功能至少有8个单独的社区请求。There have been at least eight separate community requests for this feature.

详细设计Detailed design

我们添加了一个新的赋值运算符形式We add a new form of assignment operator

assignment_operator
    : '??='
    ;

它遵循 复合赋值运算符的现有语义规则,只不过如果左侧非 null,则 elide 赋值。Which follows the existing semantic rules for compound assignment operators, except that we elide the assignment if the left-hand side is non-null. 此功能的规则如下所示。The rules for this feature are as follows.

给定 a ??= b ,其中 A 是的类型 aB 是的类型 bA0 是 if 的基础类型( A 如果 A 是可以为 null 的值类型):Given a ??= b, where A is the type of a, B is the type of b, and A0 is the underlying type of A if A is a nullable value type:

  1. 如果 A 不存在或是不可以为 null 的值类型,则会发生编译时错误。If A does not exist or is a non-nullable value type, a compile-time error occurs.
  2. 如果 B 不能隐式转换为 AA0 (如果 A0) 存在,则会发生编译时错误。If B is not implicitly convertible to A or A0 (if A0 exists), a compile-time error occurs.
  3. 如果 A0 存在且可 B 隐式转换为,并且不是动态的,则的 A0 B 类型 a ??= bA0If A0 exists and B is implicitly convertible to A0, and B is not dynamic, then the type of a ??= b is A0. a ??= b 在运行时评估为:a ??= b is evaluated at runtime as:
    var tmp = a.GetValueOrDefault();
    if (!a.HasValue) { tmp = b; a = tmp; }
    tmp
    
    除外, a 只计算一次。Except that a is only evaluated once.
  4. 否则,的类型 a ??= bAOtherwise, the type of a ??= b is A. a ??= b 在运行时将作为计算 a ?? (a = b) ,只不过 a 只计算一次。a ??= b is evaluated at runtime as a ?? (a = b), except that a is only evaluated once.

对于的类型要求的 relaxation ?? ,我们将更新其当前声明的规范,给定 a ?? b ,其中 Aa 以下类型:For the relaxation of the type requirements of ??, we update the spec where it currently states that, given a ?? b, where A is the type of a:

  1. 如果存在并且不是可以为 null 的类型或引用类型,则会发生编译时错误。If A exists and is not a nullable type or a reference type, a compile-time error occurs.

我们放宽了以下要求:We relax this requirement to:

  1. 如果存在并且是不可为 null 的值类型,则会发生编译时错误。If A exists and is a non-nullable value type, a compile-time error occurs.

这允许空合并运算符处理不受约束的类型参数,因为不存在不受约束的类型参数 T,它不是可以为 null 的类型,并且不是引用类型。This allows the null coalescing operator to work on unconstrained type parameters, as the unconstrained type parameter T exists, is not a nullable type, and is not a reference type.

缺点Drawbacks

与任何语言功能一样,我们必须回答对 c # 程序正文提供的更清晰的偿还,以使其受益于该功能。As with any language feature, we must question whether the additional complexity to the language is repaid in the additional clarity offered to the body of C# programs that would benefit from the feature.

备选方法Alternatives

程序员可以编写 (x = x ?? y)if (x == null) x = y; 或手动编写 x ?? (x = y)The programmer can write (x = x ?? y), if (x == null) x = y;, or x ?? (x = y) by hand.

未解决的问题Unresolved questions

  • [] 需要 LDM 审核[ ] Requires LDM review
  • [] 是否还支持 &&=||= 操作员?[ ] Should we also support &&= and ||= operators?

设计会议Design meetings

无。None.