C# 中的空条件运算符(?.)与空合并运算符(??)详解
在日常 C# 编程中,我们经常需要判断对象是否为空(null),
否则直接访问成员可能会抛出 NullReferenceException。
为了解决这种繁琐的空判断,C# 提供了两个非常实用的语法糖:
- ?.—— 空条件运算符(null-conditional operator)
- ??—— 空合并运算符(null-coalescing operator)
✳️ 一、空条件运算符(?.)
✅ 语法:
A?.B
💬 含义:
如果 A 不为 null,返回 A.B;
如果 A 为 null,整个表达式直接返回 null。
🧩 等价写法:
var result = (A != null) ? A.B : null;
💡 示例:
Person p = null;// 不会抛异常,直接返回 null
var name = p?.Name;    // 等价于:
string name = (p != null) ? p.Name : null;
这样写的好处是:安全访问,不会触发空引用异常。
✳️ 二、空合并运算符(??)
✅ 语法:
A ?? B
💬 含义:
- 如果左侧 A不为null,返回A;
- 如果左侧 A为null,返回右侧B。
🧩 等价写法:
var result = (A != null) ? A : B;
💡 示例:
string name = userName ?? "匿名用户";
如果 userName 为 null,则结果为 "匿名用户"。
⚙️ 三、组合使用:?. 与 ??
这两个运算符常常配合使用,用于安全访问链式对象,并提供默认值。
🌰 示例:
var name = player?.Info?.Name ?? "未知玩家";
解释:
- 
player?.Info?.Name- 如果 player或Info为null,整个表达式结果为null
 
- 如果 
- 
?? "未知玩家"- 如果左侧是 null,则使用"未知玩家"
 
- 如果左侧是 
最终效果:
👉 安全地获取玩家名称,如果取不到,就返回一个默认字符串。
⚡ 四、总结对比
| 运算符 | 名称 | 用法 | 含义 | 等价逻辑 | 
|---|---|---|---|---|
| ?. | 空条件运算符 | A?.B | 如果 A不为空则访问A.B,否则返回null | (A != null) ? A.B : null | 
| ?? | 空合并运算符 | A ?? B | 如果 A为空则返回B,否则返回A | (A != null) ? A : B | 
🎯 五、实际使用建议
- 使用 ?.:当你不确定对象是否为null,但仍要访问其成员。
- 使用 ??:当你想在值为空时提供一个默认值。
- 组合使用:player?.Info?.Name ?? "未知"是最常见的写法。
✅ 小结
| 表达式 | 说明 | 结果 | 
|---|---|---|
| A?.B | 如果 A不为空返回A.B,否则null | A == null ? null : A.B | 
| A ?? B | 如果 A不为空返回A,否则B | A == null ? B : A | 
| A?.B ?? C | 如果 A为空或A.B为空,返回C | 安全且简洁的写法 | 
✍️ 示例总结:
var playerName = player?.Info?.Name ?? "暂无玩家";
👉 安全访问对象属性链,并提供默认值。
避免 NullReferenceException,代码更优雅。
