Using Expressions in C#
- 7.12 The Null Coalescing Operator
- 7.13 Conditional Operator
- 7.14 Anonymous Function Expressions
- 7.15 Query Expressions
- 7.16 Assignment Operators
- 7.17 Expressions
- 7.18 Constant Expressions
7.12 The Null Coalescing Operator
The ?? operator is called the null coalescing operator.
null-coalescing-expression: conditional-or-expression conditional-or-expression ?? null-coalescing-expression
A null coalescing expression of the form a ?? b requires a to be of a nullable type or reference type. If a is non-null, the result of a ?? b is a; otherwise, the result is b. The operation evaluates b only if a is null.
The null coalescing operator is right-associative, meaning that operations are grouped from right to left. For example, an expression of the form a ?? b ?? c is evaluated as a ?? (b ?? c). In general terms, an expression of the form E1 ?? E2 ?? ... ?? EN returns the first of the operands that is non-null, or null if all operands are null.
The type of the expression a ?? b depends on which implicit conversions are available between the types of the operands. In order of preference, the type of a ?? b is A0, A, or B, where A is the type of a, B is the type of b (provided that b has a type), and A0 is the underlying type of A if A is a nullable type, or A otherwise. Specifically, a ?? b is processed as follows:
- If A is not a nullable type or a reference type, a compile-time error occurs.
- If A is a nullable type and an implicit conversion exists from b to A0, the result type is A0. At runtime, a is evaluated first. If a is not null, a is unwrapped to type A0, and this becomes the result. Otherwise, b is evaluated and converted to type A0, and this becomes the result.
- Otherwise, if an implicit conversion exists from b to A, the result type is A. At runtime, a is evaluated first. If a is not null, a becomes the result. Otherwise, b is evaluated and converted to type A, and this becomes the result.
- Otherwise, if b has a type B and an implicit conversion exists from A0 to B, the result type is B. At runtime, a is evaluated first. If a is not null, a is unwrapped to type A0 (unless A and A0 are the same type) and converted to type B, and this becomes the result. Otherwise, b is evaluated and becomes the result.
- Otherwise, a and b are incompatible, and a compile-time error occurs.