C#中空值校验情况说明

markdown 复制代码
# 在 C# 编程(尤其是业务开发)中,空值校验是保障程序稳定性、避免空引用异常(`NullReferenceException`)的核心手段。结合你这段物料分类新增的代码,我会从**场景+原因+示例**三个维度,清晰告诉你什么情况必须做空值校验。

### 一、必须做空值校验的核心场景

#### 1. 外部输入/入参校验(最基础也最关键)

**适用场景**:
- 方法/函数的入参(尤其是外部系统、用户输入、第三方接口传递的参数)
- 从配置文件、数据库、消息队列读取的数据
- API 接口接收的请求参数

**为什么要做**:
外部数据不受你的代码控制,可能是 null、空字符串、格式错误等,直接使用会导致程序崩溃。

**对应你代码的示例**:
```csharp
// 你的代码中对入口参数的校验(必须做)
if (receiveEventInfo == null || string.IsNullOrWhiteSpace(receiveEventInfo.Content))
{
    LogTextHelper.Warn("物料分类新增失败:接收的事件信息为空或内容为空");
    return;
}

如果不校验receiveEventInfo.Content 为 null 时,会直接抛出 NullReferenceException,导致整个方法崩溃,甚至影响调用方。

2. 反序列化/类型转换后的数据校验

适用场景

  • JSON/XML 反序列化后的对象(如你代码中 JsonConvert.DeserializeObject 的结果)
  • 数据库查询结果(如 FindSingle 查不到数据会返回 null)
  • 类型转换(如 Convert.ToInt32TryParse 失败的情况)

为什么要做 : 反序列化/查询可能因数据格式错误、数据不存在等原因返回 null,后续访问其属性(如 eventInfo.Archive)会直接报错。

对应你代码的示例

csharp 复制代码
// 反序列化后的对象校验(必须做)
if (eventInfo == null || string.IsNullOrWhiteSpace(eventInfo.Archive))
{
    LogTextHelper.Warn("物料分类新增失败:反序列化后的Archive数据为空");
    return;
}

如果不校验eventInfo 为 null 时,eventInfo.Archive 会触发空引用异常,中断业务流程。

3. 嵌套对象/多级属性访问前

适用场景

  • 访问对象的嵌套属性(如 dTOArchive.Name.ZhCN
  • 调用对象的方法(如 list.Add() 前,list 可能为 null)

为什么要做: C# 中多级属性访问时,只要其中一级为 null,就会抛出空引用异常。

对应你代码的示例

csharp 复制代码
// 空值保护:防止 Name 为 null 导致 ZhCN 访问失败
info.TypeName = dTOArchive.Name?.ZhCN ?? string.Empty;

如果不做保护dTOArchive.Name 为 null 时,dTOArchive.Name.ZhCN 会直接报错。

4. 数据库/缓存操作前的关键数据校验

适用场景

  • 插入/更新数据库前,校验核心字段(如主键、必填字段)
  • 依赖其他数据的操作(如你代码中父级分类查询结果)

为什么要做: 核心字段为空会导致数据库操作失败(如主键为空、外键关联失败),依赖数据不存在会导致业务逻辑错误。

对应你代码的示例

csharp 复制代码
// 父级分类查询结果校验(必须做)
if (p_info != null)
{
    info.ParentID = p_info.ID;
    info.ERPParentID = p_info.ERPID;
}
else
{
    string errorMsg = $"物料分类【{dTOArchive.Code}】父级数据不存在,父级ERPID:{dTOArchive.Parent}";
    LogTextHelper.Error(errorMsg);
    throw new Exception(errorMsg);
}

如果不校验p_info 为 null 时,p_info.ID 会报错,且会将无效的父级ID插入数据库,导致数据脏污。

5. 可选但建议做的场景

  • 集合类型(List/Array):访问 list.Count 前,校验 list != null
  • 可空值类型(int?/DateTime?):取值前校验 HasValue
  • 第三方组件/工具类返回值:如 File.ReadAllText 可能返回 null(文件不存在)

二、可以不做空值校验的场景(对比理解)

不是所有场景都需要校验,以下情况可省略:

  1. 内部可控的常量/初始化对象 :如 var info = new MaterialTypeInfo(); 后,info 不可能为 null,无需校验。
  2. C# 8.0+ 的可空引用类型(Nullable Reference Types) :通过 ! 操作符明确标记非空(如 name!),且代码经过严格静态检查。
  3. 单元测试中的 mock 数据:数据由你完全控制,且仅用于测试。

总结

  1. 核心原则 :只要数据来源不受代码直接控制 (外部入参、反序列化、数据库/第三方返回),或涉及多级属性访问,必须做空值校验。
  2. 校验目的:避免空引用异常、保障数据合法性、提前拦截错误(而非让程序崩溃)。
  3. 最佳实践 :校验时不仅要判断 null,还要结合业务判断"无效值"(如空字符串、0值等,如你代码中的 string.IsNullOrWhiteSpace)。
复制代码
相关推荐
wuyikeer1 天前
Spring Framework 中文官方文档
java·后端·spring
Victor3561 天前
MongoDB(61)如何避免大文档带来的性能问题?
后端
Victor3561 天前
MongoDB(62)如何避免锁定问题?
后端
wuyikeer1 天前
Spring BOOT 启动参数
java·spring boot·后端
子木HAPPY阳VIP1 天前
Ubuntu 22.04 VMware 设置固定IP配置
人工智能·后端·目标检测·机器学习·目标跟踪
人间打气筒(Ada)1 天前
如何基于 Go-kit 开发 Web 应用:从接口层到业务层再到数据层
开发语言·后端·golang
开心就好20251 天前
使用Wireshark进行TCP数据包抓包分析:三次握手与四次挥手详解
后端·ios
用户4419395054871 天前
OpenClaw服务器部署保姆级教程
后端
zdl6861 天前
springboot集成onlyoffice(部署+开发)
java·spring boot·后端
Soofjan1 天前
sync.Mutex讲解
后端