其中一种业务逻辑方法以验证代码开头:
public void Update(ProductDto dto)
{
if (dto == null)
{
throw new ArgumentNullException(nameof(dto));
}
var validContext = new ValidationContext(dto);
Validator.ValidateObject(dto, validContext);
//...
}
如果它被传递给方法null,那么我将抛出一个标准异常ArgumentNullException,并且如您所见,我不会发送任何附加信息。
在我看来,测试块是null 多余的,因为在这种情况下,它dto = null后面的表达式 无论如何都会抛出相同的异常:var validContext = new ValidationContext(dto)
如果我这样缩短方法,“实践良好的设计”会发誓吗?
public void Update(ProductDto dto)
{
var validContext = new ValidationContext(dto);
Validator.ValidateObject(dto, validContext);
//...
}

是的,我不会说这样的改变是正确的。
关键是通过这样做您将连通性引入到您的方法中。您的代码只有在以下情况下才是正确的
ValidationContext检查传入对象的null,并抛出异常,并且dto或执行其他有用的工作。在使用此代码时,需要牢记这些假设中的每一个。此外,在代码中,您还必须留下注释,解释什么
null是无效输入值,以及为什么不检查null.相比之下,开始的检查几乎是自记录代码,立即告诉读者零输入值是错误的。
你需要记住的越少越好,而且出错的可能性也越小。
另一个支持及早检查的小注意事项:如果您看到
ArgumentNullException崩溃的应用程序的堆栈跟踪,那么错误很可能在抛出异常的方法上方一帧的方法中。在深度“跳过”一个不好的论证的情况下,这种考虑是行不通的。我将对答案做一个简短的补充。
不难注意到形式的构造:
看起来相当笨重且不美观,并且有摆脱它们的愿望。因此,实现这一点的一种方法是使用合约(Code Contracts)。例如,如果使用它们,代码将如下所示:
这不仅会缩短它并使其更清晰,而且还会使您的要求更加明确。