【问题标题】:Is allowing the possibility of NullReferenceExceptions to occur a Bad Thing?允许 NullReferenceException 发生是一件坏事吗?
【发布时间】:2011-03-17 12:07:13
【问题描述】:

我正在玩 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...

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

【问题讨论】:

    标签: c# nullreferenceexception pex


    【解决方案1】:

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

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

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

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

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

    【讨论】:

    • 我完全同意乔恩的观点。您应该检查那些不受您控制的参数是否为 null。当您验证公共方法的参数时,无需对私有方法的参数执行这些检查。
    • 好的,所以每当 Pex 说它遇到 NullReferenceException 时,我是否应该进行空测试并在该方法的顶部抛出 ArgumentNullException?
    • @Calanus:可能,可能不会。您需要找出错误的来源,并采取相应措施。例如,它可能在您不想添加参数测试的私有方法中,但在调用堆栈更高的公共方法中进行检查是合适的。
    • 考虑使用代码契约进行参数空值检查visualstudiogallery.msdn.microsoft.com/…
    【解决方案2】:

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

    【讨论】:

      【解决方案3】:

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

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

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

      所以你可以使用:

      myString.NullSafe().ToUpper()
      

      【讨论】:

        【解决方案4】:

        即使从简单的诊断角度来看,您还能从哪些方面获得更多信息 - NullReferenceException 还是 ArguementNullException

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

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

        • 有些东西是空的,在某处,我可能没想到会是这样。
        • 我可能需要调试才能找到错误。

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

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

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

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

        这是不对的。

        throw new ArgumentNullException("VariableName");
        

        没错。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2010-09-21
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-08-28
          • 1970-01-01
          • 2011-03-08
          相关资源
          最近更新 更多