用于空值的正当例外

时间:2010-05-21 18:54:23

标签: c# exception-handling

在下面的示例中,我们有两个不同的例外,我们想要沟通。

//constructor
public Main(string arg){
   if(arg==null)
      throw new ArgumentNullException("arg");

  Thing foo=GetFoo(arg);

  if(foo==null)
     throw new NullReferenceException("foo is null");    
}

这是两种异常类型的正确方法吗?

9 个答案:

答案 0 :(得分:6)

第一个例外肯定是正确的。这是第二个棘手的问题。

这里有两种可能性:

  • GetFoo()并不意味着永远返回null。在那种情况下,我们基本上证明了GetFoo()中的错误。我不确定这里最好的例外,将ContractException(来自代码合同)放在一边。基本上你想要像<{1}}这样的 - 这是一个例外,意思是“世界变得疯狂:这不仅仅是一个外部出乎意料的结果,这里有一个错误。”
  • 由于ContractException的价值,
  • GetFoo()可以合法地返回null。在这种情况下,我建议arg(但 ArgumentException)可能是合适的。另一方面,使用参数在之后抛出ArgumentNullException 是很奇怪的。

ArgumentException在这里不太合适,但我可能想要将它作为最接近合同失败的东西...

编辑:根据Aaronaught的回答,您还应该考虑创建自己的例外。

答案 1 :(得分:5)

You should never explicitly throw a NullReferenceException

如果null作为参数传递,则应该使用参数名称抛出ArgumentNullException
如果其他一些事情是null,您可能应该使用描述性消息抛出InvalidOperationException

答案 2 :(得分:3)

永远不要抛出NullReferenceException。这并不意味着传递了null。这意味着尝试使用 null。

答案 3 :(得分:1)

ArgumentNullException显然是正确的,而第二个则取决于您的业务背景。

答案 4 :(得分:1)

ArgumentNullException是第一次检查的明显选择。

由于看起来Thing是从输入参数派生的,我会抛出ArgumentException来指示无法从指定的输入构造Thing。毕竟,(可能无论如何)它是输入的问题,而不是用于构造Thing的算法。

答案 5 :(得分:1)

ArgumentNullException

  

将空引用[...]传递给不接受它作为有效参数的方法时引发的异常。

NullReferenceException

  

尝试取消引用空对象引用时引发的异常。

“foo为null”是一条糟糕的错误消息,因为foo本地变量。更好的错误消息是"GetFoo returned null for the input " + arg。此外,如果GetFoo返回null时将抛出异常,则使其抛出相应的异常。

答案 6 :(得分:1)

对于第一种情况,我会继续说ArgumentNullException是正确的。

对于第二种情况,我真的很惊讶没有其他人这样说过:你应该为此制作自己的Exception课程。内置的系统异常都不合适:

  • ArgumentException暗示论证本身在某种程度上是无效的;这不是真的。争论很好,只是后来意外发生了。

  • InvalidOperationException 几乎正确,但该异常通常被解释为意味着在错误的时间调用操作,例如尝试在连接上执行命令尚未开放的。换句话说,它表示对象的当前状态与您尝试执行的特定操作之间不匹配;这在这里也不适用。

  • NullReferenceException就出来了。这是一个保留的异常,意味着完全不同的东西(程序实际上试图 deference null引用)。

这些都不对。你真正需要做的是专门传达出错的地方,为了做到这一点,你应该创建一个MissingThingException。该异常可以在其消息/详细信息中包含事物的ID(可能是arg)。这对于调用者来说是最好的,因为它允许他们在知道如何处理它时捕获特定的异常,并且对最终用户也是最好的,因为它允许您留下有意义的错误消息。

摘要:为此创建自定义异常类。

答案 7 :(得分:1)

根据Code Analysis blog,异常使用应如下所示:

  • ArgumentOutOfRangeException如果您正在测试的输入值不在预期的值集中。 (例如,如果参数表示命令名称,并且提供的命令名称无效)

  • ArgumentNullException如果输入值不能为null,则执行该函数。

  • ArgumentException如果输入值无效(例如,如果传入空字符串,但不允许空字符串)

答案 8 :(得分:0)

我认为这些都是正确的。对我来说,选择异常类型实际上只是关于它是否能清楚地描述已经发生的错误。我总是从另一个没有见过我班级的开发者的角度思考它。是否会为其他开发者提供足够的信息以快速准确地找到问题?