在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";