NullReferenceException vs ArgumentNullException

时间:2016-09-15 20:57:17

标签: c# exception nullreferenceexception

我正在阅读this post,回答者提到他ArgumentNullException优先于NullReferenceException

MSDN提及NullReferenceException

  

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

ArgumentNullException they上说:

  

将空引用(在Visual Basic中为Nothing)传递给不接受它作为有效参数的方法时引发的异常。

回答者似乎说你可以使用。

是否有任何理由或任何情况我应该选择其中一种?

P.S。

我知道这个问题可能是基于意见的。 我想要事实,背景和情况。我对个人偏好并不感兴趣。

3 个答案:

答案 0 :(得分:11)

如果您在代码中明确抛出异常,则应选择ArgumentNullException

当取消引用空引用/指针时,CLR会自动抛出

NullReferenceException

unsafe
{
    int* ptr = null; // Null pointer.
    int val = *ptr; // NullReferenceException thrown.
}

最常见的情况是在空引用上调用方法或属性时:

string s = null;
string substring = s.Substring(0, 2); // NullReferenceException thrown.

在大多数情况下,不应在代码中明确抛出NullReferenceException

ArgumentNullException用于检查将空引用作为参数传递的情况,通常是为了防止NullReferenceException

static string firstTwo(string s)
{
    if (s == null)
    {
        throw new ArgumentNullException("s");
    }
    return s.Substring(0, 2); // without the original check, this line would throw a NullReferenceException if s were null.
}

此检查的目的是清楚地让调用者知道传递了null并且不允许null。否则,如果你只是抛出NullReferenceException,调用者只会看到

  

对象引用未设置为对象的实例

这个没有意义(使用支票时):

  

值不能为空。参数名称:s

答案 1 :(得分:3)

NullReferenceException 永远故意按惯例抛出。它标志着无意的预先违规。因此,它几乎总是发出错误信号。该错误发生在抛出异常的代码中。

按惯例,所有Argument*Exception都应视为错误。其中99%是真正的错误。 1%不是真正的错误,但值得花时间来阻止它们并抛出更有意义的异常类型来维护惯例。

使用NullReferenceException表示您拒绝传递的参数。 NullReferenceException表示抛出此异常的代码的程序员发生了错误。

Argument*Exception视为运行时提供的失败断言。 {{1}}的意思是“我想到了这个案例,我有意识地拒绝了它。”。

答案 2 :(得分:0)

即使框架扩展方法看起来像是会引发NullReferenceException,而是抛出ArgumentNullExceptions

List<string> list = null;
var results = list.Select(x => x); //ArgumentNullException

从查看代码(并且事先没有知道Select是一种扩展方法)这个应该抛出一个NullReferenceException ...如果框架甚至没有抛出它们在这种情况下,我总是坚持使用ArgumentNullException