【问题标题】:What exception should I throw for an unexpected null value?我应该为意外的空值抛出什么异常?
【发布时间】:2015-12-08 18:55:08
【问题描述】:

我从事 .NET 开发已有十多年了,所以这是一个我从来不知道答案的可耻问题。我明白了——如果一个参数为空,我可以抛出一个 ArgumentNullException。如果我尝试取消引用 null 值,将引发 NullReferenceException。

但是如果我有如下代码怎么办:

var someVitalObject = someServiceReference.GetVitalObject();

if (someVitalObject == null)
{
  throw new IDontKnowWhatException(); // what exception should I throw here?
}

现在,这不一定是服务的问题,应该早先抛出异常。

【问题讨论】:

  • NullReferenceException?
  • 这是执行流程中的错误吗?这会导致您的应用程序终止吗?也许更多的上下文将帮助我们更好地理解问题。
  • GetVitalObject() 是否违反了它的合同,或者返回 null 是否有效,但在这种情况下不是?
  • API 是否对对象是否可以为空做一些保证?如果是这样,它可能更像是一个断言失败(使用 Trace.Assert)。否则,像 VitalObjectNotFoundException 这样的自定义异常将是合适的。
  • 在我的例子中,为了简单起见,假设我正在检查缓存的状态以查看它是否存储了“重要对象”。到那时应该会,如果没有,那就是个问题。

标签: c# exception exception-handling


【解决方案1】:

如果不看更多上下文很难说,但也许System.InvalidOperationException

当方法调用对于对象的当前状态无效时引发的异常。

【讨论】:

    【解决方案2】:

    对于传递给函数的对象,我通常使用 ArgumentNullException。其他任何与 null 相关的内容我都使用 InvalidOperationException。在特殊情况下,如果有意义,我将创建一个自定义异常。

    【讨论】:

      【解决方案3】:

      我只会在直接检查方法参数时使用 System.ArgumentNullException,而不是在验证某些调用的结果时使用。

      我抛出的异常类型很大程度上取决于上下文。但在这种情况下,我可能会选择一个自定义异常,例如:

      public class VitalObjectNotAcquiredException : Exception { ... }
      

      【讨论】:

        【解决方案4】:

        考虑创建自己的Exception 类,继承自ApplicationExceptionException

        public sealed class MyException : Exception
        {
            ...
        }
        

        因此,您将能够控制在其中存储什么样的信息。

        【讨论】:

        【解决方案5】:

        就个人而言,我会根据 GetVitalObject 方法合同进行选择。如果此方法应该返回一个非空对象,我会更改它,以便在这种情况下引发异常。

        如果您无法控制该方法,或者如果返回空值是正确的(但不是在您的上下文中),我会使用 Mark 和 Dmitry 已经说过的自定义异常。

        【讨论】:

          【解决方案6】:

          我会抛出一个System.NullReferenceException。或者,如果您对此不满意,您可以为您自己的目的使用更专业的空引用异常类型从中派生。

          【讨论】:

          • 不,这通常是取消引用空引用的结果。这基本上表明您没有进行了足够的检查。基本上我会在我的日志中发现一个误导性的异常。
          • 投掷NullReferenceException 会非常误导。
          • 我认为你永远不应该自己扔一个。 NullReferenceException 更像是您在使用它之前忘记自己检查 null 的指示。
          • 我永远不会。将 NRE 留给运行时,因为它指出了一个开发错误。对于方法参数,通常是 ArgumentNullException,或者其他一些可能更详细的异常
          • @roryap:我不知道您所说的“已经取消引用的引用”是什么意思,或者“访问空引用”是什么意思。当您拥有foo.Bar 时,这就是取消引用foo 的值...所以如果foonull,则会引发异常。在这种情况下,OP 没有取消引用 null 引用 - 他刚刚发现它是空的。
          猜你喜欢
          • 1970-01-01
          • 2015-10-04
          • 2023-03-21
          • 1970-01-01
          • 1970-01-01
          • 2020-08-21
          • 2014-02-15
          • 1970-01-01
          • 2015-05-12
          相关资源
          最近更新 更多