1

我正在玩 Pex 和 Moles,在运行 Pex 后发现 Pex 所说的几乎所有失败的测试都是因为 NullReferenceExceptions 是“允许的”。阅读 Pex 文档,我发现了以下内容:

如果较高级别的组件将格式错误的数据传递给较低级别​​的组件,而较低级别的组件拒绝了该组件,则应首先阻止较高级别的组件这样做。

所以上面的建议是我们应该在调用其他方法/类之前测试空值,例如:

if(foo == null)
   throw new ArgumentNullException("its null and this shouldn't happen")
else
   Bar(foo); //won't get a null reference exception here because we checked first...

恕我直言,全面检查空值对性能和代码膨胀的原因并没有太大吸引力,但我想听听其他人怎么说....

4

4 回答 4

9

是的,你应该在使用它们之前验证你的论点,IMO。

NullReferenceException应在使用未预料到的空值时发生。它永远不应该被显式抛出,并且表明最终抛出它的方法级别的问题,或者它被调用的东西。

ArgumentNullException表示调用堆栈中的方法中的错误比抛出它的方法更早。(通常,但不总是,直接调用者。)

越早抛出表示问题的异常,就越容易查明空值首先进入的位置,并且“坏数据”在其他地方产生不良影响的可能性越小(例如,覆盖准备好的文件)在意识到数据实际上为空之前将数据写入其中)。

如果您对如何调用内部或私有方法有信心,那么不在那里执行检查可能是合适的,但对于公共方法,我相信参数验证几乎总是合适的。

于 2011-03-17T12:10:56.057 回答
3

是的,我同意。ANullReferenceException是尝试在作为空引用的变量上调用成员的结果。这意味着没有安全措施来验证调用成员是否是合法操作,这在我看来是一件坏事。在使用之前,您应该始终不信任输入并验证您可以安全使用它

于 2011-03-17T12:12:52.140 回答
1

将参数传递给公开服务的函数时,检查 NULL 始终是一个好习惯。NULL 检查的其余部分归结为常识,但它很有用,您基本上可以使用辅助方法来完成它。

最烦人的 NULL 检查是字符串。它们可能非常讨厌,但我使用扩展方法来克服它:

public static class StringExtensions
{
    public static string NullSafe(this string s)
    {
        return s ?? string.Empty;
    }
}

所以你可以使用:

myString.NullSafe().ToUpper()
于 2011-03-17T12:15:02.767 回答
1

即使从简单的诊断角度来看,您还能获得更多关于NullReferenceExceptionArguementNullException的信息吗?

更进一步,将堆栈跟踪从图片中取出。您的两条消息可能是:

NullReferenceException: “对象引用未设置为对象的实例。”

  • 有些东西是空的,在某个地方,我可能没想到它会是。
  • 我可能需要调试才能找到错误。

ArguementNullException: “System.ArgumentNullException:MyVariable 不能为空。”

  • 我知道某些 null 被传递给了一个方法。
  • 很有可能,通过变量名,我可以将其缩小到一组较小的可能方法
  • 我可能仍然需要调试,但我应该能够知道一些放置断点的一般位置。

此外,检查您的语法并阅读有关您应该传递给 ArgumentNullException 构造函数的信息。

throw new ArgumentNullException("its null and this shouldn't happen");

那是不对的。

throw new ArgumentNullException("VariableName");

没错。

于 2011-05-19T18:15:16.663 回答