null是引用类型的缺失状态,表示变量未指向任何对象;访问null引用会触发nullreferenceexception;c#通过可为null的引用类型(如string?)、空条件运算符(?.)、空合并运算符(??)及编译时静态分析协同管理null风险。

“null”不是值,而是引用类型的缺失状态——它表示变量当前不指向任何对象实例。这种“空”不是偶然出现的,而是设计中必须主动管理的状态。
为什么 null 会引发运行时异常
当代码尝试通过 . 或 [] 访问一个为 null 的引用时(例如 message.Length 或 list[0]),就会触发 NullReferenceException。这不是语法错误,而是在运行时才暴露的逻辑漏洞。
- 编译器默认无法判断引用是否为空,除非启用可为 null 的引用类型功能
- 未初始化的引用类型字段、方法返回 null、数据库查询无结果等,都是常见 null 来源
- 值类型(如
int、DateTime)本身不可为 null,但int?或DateTime?是例外
用类型系统把“空”显式说出来
C# 允许你在声明时就表明意图:这个引用是否允许为空。
-
string name;—— 在可为 null 上下文中,默认要求非 null;赋 null 会警告 -
string? nickname;—— 明确允许 null,但访问前仍需检查(如if (nickname != null)) - 构造函数参数、属性、返回值都可用
?标记,让 API 含义更清晰
编译器帮你提前发现风险
启用可为 null 引用类型后,编译器会在编译阶段跟踪每个变量的 null 状态:
- not-null:已确认不为 null(例如刚 new 出的对象、已做过 null 检查的变量)
- maybe-null:可能为 null(例如方法返回值未标注、用户输入、集合索引访问)
- 对 maybe-null 变量直接调用成员,编译器立即报 CS8602 警告
不只是加个问号,关键是配合使用
单独写 string? 不足以解决问题,真正起作用的是整套协作机制:
- 用
[NotNullWhen(true)]等属性注解方法,告诉编译器“调用TryParse返回 true 时,out 参数一定非 null” - 用空合并运算符
??提供默认值,或用空条件运算符?.安全链式调用 - 在项目文件中开启
<nullable>enable</nullable>,或用#nullable enable控制作用域











