在C#中,双问号 ?? 是一个 空合并运算符(Null-Coalescing Operator),用于处理可能为 null 的值,并提供一个默认值。它的作用是:如果左边的表达式为 null,则返回右边的值;否则返回左边的值。
语法格式
result = expression1 ?? expression2;
expression1:可以是任何可能为null的表达式(包括可空值类型或引用类型)。expression2:当expression1为null时,返回expression2的值。- 返回值:返回
expression1或expression2的非null值,类型需兼容。
示例
基本用法
int? number = null;
int result = number ?? 10; // 如果 number 为 null,则 result = 10
Console.WriteLine(result); // 输出:10
引用类型
string name = null;
string displayName = name ?? "Guest"; // 如果 name 为 null,则 displayName = "Guest"
Console.WriteLine(displayName); // 输出:Guest
结合可空引用类型
(C# 8.0+) 启用 可空引用类型(Nullable Reference Types, NRT) 后,?? 运算符更常用:
// 启用可空引用类型后,string? 表示可能为 null 的字符串
string? email = null;
string validEmail = email ?? "[email protected]";
Console.WriteLine(validEmail); // 输出:[email protected]
空合并赋值运算符
C# 8.0 引入了 空合并赋值运算符 ??=,用于简化赋值操作:
// 如果 left 为 null,则赋值为 right
left ??= right;
示例:
string? username = null;
username ??= "Anonymous"; // 如果 username 为 null,则赋值为 "Anonymous"
Console.WriteLine(username); // 输出:Anonymous
??相关的其他特性
模式匹配(Pattern Matching)
在 switch 表达式中,?? 可以用于提供默认值:
int? value = null;
int result = value switch {
null => 0, // 如果 value 为 null,返回 0
_ => value.Value // 否则返回值
};
// 等价于:result = value ?? 0;
级联空合并
C# 9.0 引入了 空条件运算符 ?. 和 空合并 ?? 的组合,可以简化嵌套的 null 检查:
Person person = null;
string name = person?.Name ?? "Unknown"; // 如果 person 或 person.Name 为 null,返回 "Unknown"
注意事项
- 类型兼容性:
expression1和expression2的类型必须兼容。例如:
object obj = "text";
string s = obj ?? "default"; // 允许,因为 obj 可以转换为 string
int? num = null;
double d = num ?? 5.0; // 允许,因为 5.0 是 double 类型
- 与
??=的区别:
??=是赋值运算符,而??是表达式运算符。
- 与
?运算符的区别:
?.是 空条件运算符,用于安全访问对象属性(如obj?.Method())。??是 空合并运算符,用于提供默认值。
总结
??的核心作用:提供一个默认值,避免因null引发的NullReferenceException。- 适用场景:处理可能为
null的值类型或引用类型,确保程序的健壮性。 - 新特性:C# 8.0 的
??=和可空引用类型进一步简化了null处理的代码。
如果需要更复杂的 null 检查逻辑(如链式调用或条件赋值),可以结合 ?. 和 ?? 使用,例如:
string result = obj?.GetProperty()?.GetValue() ?? "Default Value";