C#中的可空类型和问号

在C#中,双问号 ?? 是一个 空合并运算符(Null-Coalescing Operator),用于处理可能为 null 的值,并提供一个默认值。它的作用是:如果左边的表达式为 null,则返回右边的值;否则返回左边的值

语法格式

result = expression1 ?? expression2;
  • expression1:可以是任何可能为 null 的表达式(包括可空值类型或引用类型)。
  • expression2:当 expression1null 时,返回 expression2 的值。
  • 返回值:返回 expression1expression2 的非 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"

注意事项

  1. 类型兼容性
  • expression1expression2 的类型必须兼容。例如:
object obj = "text";
string s = obj ?? "default"; // 允许,因为 obj 可以转换为 string
int? num = null;
double d = num ?? 5.0; // 允许,因为 5.0 是 double 类型
  1. ??= 的区别
  • ??= 是赋值运算符,而 ?? 是表达式运算符。
  1. ? 运算符的区别
  • ?.空条件运算符,用于安全访问对象属性(如 obj?.Method() )。
  • ??空合并运算符,用于提供默认值。

总结

  • ?? 的核心作用:提供一个默认值,避免因 null 引发的 NullReferenceException
  • 适用场景:处理可能为 null 的值类型或引用类型,确保程序的健壮性。
  • 新特性:C# 8.0 的 ??= 和可空引用类型进一步简化了 null 处理的代码。

如果需要更复杂的 null 检查逻辑(如链式调用或条件赋值),可以结合 ?.?? 使用,例如:

string result = obj?.GetProperty()?.GetValue() ?? "Default Value";