?? 运算符
?? 运算符称为 null 合并运算符,用于定义可以为 null 值的类型和引用类型的默认值。如果此运算符的左操作数不为 null,则此运算符将返回左操作数;否则返回右操作数。
a ?? b 形式的空合并表达式要求 a 为可以为 null 的类型或引用类型。如果 a 为非 null,则 a ?? b 的结果为 a;否则,结果为 b。仅当 a 为 null 时,该操作才计算 b。
空合并运算符为右结合运算符,表示操作从右向左进行组合。例如,a ?? b ?? c 形式的表达式按 a ?? (b ?? c) 计算。概括地说,E1 ?? E2 ?? ... ?? EN 形式的表达式返回第一个非 null 的操作数,如果所有操作数都为 null,则返回 null。
表达式 a ?? b 的类型取决于两个操作数类型之间有哪些隐式转换可用。按照优先级顺序,a ?? b 的类型为 A0、A 或 B,其中 a 的类型为 A,b 的类型为 B(如果 b 具有类型),A0 是 A 的基础类型(如果 A 为可以为 null 的类型或者 A 是其他允许的类型)。具体而言,a ?? b 的处理过程如下:
· 如果 A 不是可以为 null 的类型或引用类型,则会发生编译时错误。
· 如果 A 是可为 null 的类型并且存在从 b 到 A0 的隐式转换,则结果类型为 A0。在运行时,首先计算 a。如果 a 不为 null,则 a 解包为类型 A0,这即是结果。否则,计算 b 并转换为类型 A0,这即是结果。
· 否则,如果存在从 b 到 A 的隐式转换,则结果类型为 A。在运行时,首先计算 a。如果 a 不为 null,则 a 即是结果。否则,计算 b 并转换为类型 A,这即是结果。
· 否则,如果 b 具有类型 B 并且存在从 A0 到 B 的隐式转换,则结果类型为 B。在运行时,首先计算 a。如果 a 不为 null,则 a 解包为类型 A0(除非 A 和 A0 类型相同)并转换为类型 B,这即是结果。否则,计算 b 并且 b 作为结果。
· 否则,a 和 b 不兼容,并发生编译时错误。
备注
可以为 null 的类型可以包含值,或者可以是未定义的。?? 运算符定义当可以为 null 的类型分配给非可以为 null 的类型时返回的默认值。如果在尝试将可以为 null 值的类型分配给不可以为 null 值的类型时没有使用 ?? 运算符,则会生成编译时错误。如果使用强制转换,且当前还未定义可以为 null 值的类型,则会引发 InvalidOperationException异常。
有关更多信息,请参见可空类型(C# 编程指南)。
即使 ?? 运算符的两个参数都是常量,也不能将其结果视为常量。
示例
C# | |
---|---|
class NullCoalesce { static int? GetNullableInt() { return null; } static string GetStringValue() { return null; } static void Main() { // ?? operator example. int? x = null; // y = x, unless x is null, in which case y = -1. int y = x ?? -1; // Assign i to return value of method, unless // return value is null, in which case assign // default value of int to i. int i = GetNullableInt() ?? default(int); string s = GetStringValue(); // ?? also works with reference types. // Display contents of s, unless s is null, // in which case display "Unspecified". Console.WriteLine(s ?? "Unspecified"); } } |