在下面的示例中,我们有两个不同的例外,我们想要沟通。
//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");
}
这是两种异常类型的正确方法吗?
答案 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)
将空引用[...]传递给不接受它作为有效参数的方法时引发的异常。
尝试取消引用空对象引用时引发的异常。
“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)
我认为这些都是正确的。对我来说,选择异常类型实际上只是关于它是否能清楚地描述已经发生的错误。我总是从另一个没有见过我班级的开发者的角度思考它。是否会为其他开发者提供足够的信息以快速准确地找到问题?