c# 参数验证
检查参数是否为空是一种非常普遍的做法:
public void DoSomething ( Foo foo )
{
if (foo is null )
{
throw new ArgumentNullException( nameof (foo));
}
}
在这个博客中,我想谈谈参数null验证:为什么,何时以及如何。
为什么
许多编码风格规则中都建议使用此方法,许多开源项目中都遵循它,但是为什么呢? 如果不检查参数会怎样? 参数null验证有什么好处?
让我们谈谈以下C#代码:
public void PrintCar ( Car car )
{
if (car == null )
{
throw new ArgumentNullException( nameof (foo));
}
Console.WriteLine(car.Name);
}
在这种情况下,如果不检查参数是否为null,它将引发NullReferenceException; 如果我们检查参数,它将引发ArgumentNullException。 看起来好像缺少了NullReferenceException,但实际上我们得到了一个新的ArgumentNullException。 呼叫者仍然必须处理它。 例外数量完全没有变化。
称伏地魔为“你知道谁”不能杀死他。
如果方法捕获到异常并且没有能力处理异常,是否需要检查null参数?
不同的人有不同的意见。
在博客<为什么我从不对参数进行空检查>中 ,作者指出,如果您捕获异常并将其忽略,则没有任何意义。 该错误必须是可见的,才能轻松纠正。
我认为,在大多数情况下,参数空验证是必要且有用的。
第一个原因是NullReferenceException与ArgumentNullException不同。 例外的名称可以帮助我们找到责任方。 如果调用该方法并获得ArgumentNullException ,则可能会发现参数有问题。 就像HTTP中的40x和50x状态代码一样。 错误的请求与服务器错误完全不同。
第二个原因是,我们服务中的大多数方法不是无状态的。 在这些有状态方法中,方法中间的异常将使状态混乱,并且我们不能轻易回滚。
看一下这个例子:
public void CarCounter ( Car car )
{
// #1
this .CarCount += 1 ;
// #2
this .CarNames.Add(car.Name);
}
当car为null时,它将在第2行引发异常。 但是,#1行中有状态更新。 这可能会错误地修改计数。 我们需要一种类似于数据库中事务的机制来回滚该方法的已执行部分。 这可能非常复杂。 在某些情况下,例如通知,这些动作是不可撤销的。
结论是,在大多数情况下,参数空验证是必要且有用的。 它可以避免不应执行的执行,并且可以指定意外异常的责任。
什么时候
如上所述,检查null参数是有意义的。 但是我们应该检查项目中的所有方法参数吗?
这取决于。
对于公共方法,我们不知道调用方将传递什么参数,我们应该在业务逻辑之前检查空参数。
对于私有方法,我们不需要检查,因为我们应该知道该方法的调用方式和调用位置。 在这种情况下,应在调用方法之前检查null变量。
启用CA1062警告是一个不错的选择。 有了这个警告,我们不必担心何时验证参数。 只是考虑应该使用哪个访问修饰符,公共的还是私有的。
怎么样
下面的问题是,如何检查空参数。 验证代码冗长且无用。 在任何地方验证空参数都会使代码难以理解。
在博客<C#期货:简化参数无效验证>中 ,作者经历了许多方法来验证参数。 的 关于bang运算符的C#提案#2145非常有趣,我真的很期待它。
鉴于不赞成使用代码合同,将验证包装到Helper中是更好的选择:
internal static class ThrowIf
{
public static class Argument
{
public static void IsNull<T>(T argument, string name)
{
if (argument is null )
{
throw new ArgumentNullException(name);
}
}
}
}
public void DoSomething ( Foo foo )
{
ThrowIf.Argument.IsNull(foo, nameof (foo));
}
如果您还有其他解决方案,请告诉我。 谢谢。
谢谢。
参考文献:
- 避免在Java中检查Null语句
- 为什么我从不对参数进行Null检查
- 为参数空检查实现异常帮助器类
- 代码合同| 微软文件
- 代码合同| MS研究
- 借助Code Contracts支持的优雅的方法参数验证
- 您是否从私有方法中抛出argumentsexception或argumentsnullexception?
- 我应该在私有/内部方法中抛出空参数吗?
翻译自: https://hackernoon.com/c-parameter-null-validation-explained-9h113uca
c# 参数验证