是否需要对方法传入的所有引用类型参数进行非空检查?
是否需要对方法的所有引用类型参数做非空检查?
通常建议对公开方法的引用类型参数做非空检查,但也要根据实际场景灵活判断,下面结合你的代码示例逐一说明:
几种写法的分析
选项1:不进行检查
这种写法的问题很直接——如果调用者传入null,错误会在a.DoSomething()或b.DoSomething()执行时才爆发,抛出NullReferenceException。此时排查问题需要定位到具体执行代码,不如在方法入口就明确抛出ArgumentNullException,直接告诉调用者哪个参数不符合要求。
代码示例:
public void Foo(A a, B b) { a.DoSomething(); b.DoSomething(); }
选项2:进行检查
这是.NET生态里推荐的标准写法,在方法最开头就主动校验参数合法性。建议补充参数名到异常里,用nameof避免硬编码,重构时更安全:
public void Foo(A a, B b) { if (a is null) throw new ArgumentNullException(nameof(a)); if (b is null) throw new ArgumentNullException(nameof(b)); a.DoSomething(); b.DoSomething(); }
关于Contract.Requires无效的问题
Code Contracts不是开箱即用的,需要额外配置才能生效:
- 必须安装
Microsoft.CodeContractsNuGet包; - 在项目属性的
Code Contracts选项卡中,启用运行时契约检查。
没做这些配置的话,Contract.Requires不会在运行时执行任何检查,所以看起来完全没作用。另外要注意,.NET Core/.NET 5+对Code Contracts的支持已经比较有限,现在更推荐显式null检查或者C# 8.0+的可为空引用类型。
不需要做非空检查的场景
- 私有方法:如果调用方都是你自己控制的代码,且能确保不会传入null,可以省略检查;
- 参数允许为null:如果方法设计本身允许参数为null,那不仅不用检查,还要做好null的处理逻辑(比如
if (a != null) a.DoSomething();)。
更简洁的替代方案(.NET 6+)
.NET 6提供了ArgumentNullException.ThrowIfNull静态方法,能简化非空检查代码:
public void Foo(A a, B b) { ArgumentNullException.ThrowIfNull(a); ArgumentNullException.ThrowIfNull(b); a.DoSomething(); b.DoSomething(); }
如果是C# 8.0+项目,还可以启用可为空引用类型,让编译器在编译阶段就帮你排查潜在的null传入问题,和运行时检查形成双重保障。
内容的提问来源于stack exchange,提问作者Alex
相关产品推荐
相关产品推荐

