用 == null 判断引用类型最安全,因默认调用 ReferenceEquals;int? 等可空类型可用 == null 或 HasValue;慎用装箱拆箱避免 InvalidCastException。

直接用 == null 判断引用类型最安全
对引用类型(如 string、object、自定义类实例),== 运算符默认调用 ReferenceEquals,能准确识别是否为 null。这是最常用也最不易出错的方式。
- 不要用
.Equals(null)—— 会抛NullReferenceException - 避免重载了
==的自定义类型(极少见),此时应优先查文档或改用ReferenceEquals(obj, null) -
string是特例:它重载了==,但行为仍符合预期("" == null为false),所以放心用
值类型不能为 null,但可空值类型(Nullable)要特殊处理
int、DateTime 等非泛型值类型永远不为 null,编译器甚至不允许写 int x = null;。但 int?(即 Nullable)可以,判断方式不同:
- 用
obj == null对int?是合法且推荐的(编译器自动转换为HasValue == false) - 也可显式调用
obj.HasValue,语义更清晰,尤其在复杂条件中 - 别用
obj == default(int?)—— 虽然结果相同,但可读性差,且容易和默认值逻辑混淆
使用 ?? 和 ?. 避免重复判空
频繁判空时,C# 提供了更简洁的语法,本质仍是基于 null 判断,但大幅减少样板代码:
-
var name = person?.Name ?? "Unknown":若person为null,整个表达式短路,直接取右值 -
list?.Count:若list为null,返回null(如果Count是int,则需配合??或转为int?) - 注意
?.只对引用类型或可空值类型有效;对普通int用?.ToString()会编译失败
警惕装箱导致的意外 null 判断失效
当把可空值类型(如 int?)赋给 object 时会发生装箱,若其值为 null,装箱后是真正的 null 引用;但若你再把它拆箱回 int?,必须确保类型一致,否则会抛异常:
int? x = null; object o = x; // 装箱 → o 为 null int? y = (int?)o; // 正确:拆箱回 int? int z = (int)o; // 错误:拆箱为 int 会抛 InvalidCastException
这种场景下,o == null 返回 true 是对的,但后续操作必须匹配原始可空类型,否则判空通过后仍可能崩溃。









