C# 中 ?、?.、??、??= 运算符的用法详解
在 C# 开发中,正确处理 null 值是避免运行时错误的关键。本文详细解析了四个核心运算符:? 声明可空类型,?? 获取默认值,?. 安全访问成员,以及 ?=? 条件赋值,助您写出更健壮的代码。
1. 可空类型修饰符 ?
在 C# 中,引用类型(如 string)默认可以为 null,但值类型(如 int、DateTime)默认不能。若试图将 null 赋给不可空的值类型,编译器会报错。为了使值类型也能表示“无值”状态,C# 提供了可空类型机制,使用后缀 ? 表示,其通用形式为 T?,本质上是 Nullable<T> 的语法糖。
以下代码展示了如何声明和使用可空值类型:
// 引用类型本身支持 null
string str = null;
// 以下语句编译报错,因为 int 是值类型,默认可为空
// int i = null;
// 使用 '?' 使值类型变为可空类型
int? i = null; // 表示可空的整数
DateTime? time = null; // 表示可空的时间
2. 空合并运算符 ??
空合并运算符 ?? 用于确定对象是否为 null。如果左侧操作数不为 null,则返回该操作数的值;如果左侧为 null,则计算并返回右侧操作数的值。它常用于为变量提供默认值。
// 当 a 不为空时返回 a,为 null 时返回 b
var c = a ?? b;
3. 空传播运算符 ?.(条件访问)
当需要对可能为 null 的对象进行属性或方法访问时,直接使用点号(.)可能会抛出 NullReferenceException。空传播运算符 ?.(也称为条件访问运算符)可以安全地执行此操作:如果对象为 null,则表达式立即返回 null,后续链式调用不再执行。
假设有一个 Person 对象,以下两段代码逻辑等效。第一段使用了 ?. 进行简化:
// 仅当 Person 非 null 时,才访问其 Name 属性
// 注意:原草稿示例逻辑有误,修正为标准用法:
// 假设我们要获取 Person.Name 的值,若 Person 为 null 则返回 null
string name = Person?.Name;
其展开后的等价代码如下(通常配合三元运算符使用):
string name = Person == null ? null : Person.Name;
提示:在使用 ?. 时,确保整个表达式的结果类型与目标属性的可空性匹配。例如,访问值类型的 nullable 属性时需小心装箱问题。
4. 空合并赋值运算符 ??=
从 C# 8.0 开始,引入了空合并赋值运算符 ?=?。这是一个组合操作符,仅当左侧操作数的求值结果为 null 时,才会将右侧操作数的值赋值给左侧操作数。如果左侧不为 null,右侧操作数甚至不会被评估。这在初始化集合或配置对象时非常有用。
List<int> numbers = null;
int? i = null;
// 由于 numbers 为 null,执行赋值初始化
numbers ??= new List<int>();
// i 为 null,赋予默认值 17
numbers.Add(i ??= 17);
// i 当前为 17(非 null),故不执行赋值,再次添加 17
numbers.Add(i ??= 20);
Console.WriteLine(string.Join(" ", numbers)); // 输出:17 17
Console.WriteLine(i); // 输出:17本站声明
本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。













