NullReferenceException 与 ArgumentNullException

NullReferenceException vs ArgumentNullException

我正在阅读 this post,回答者提到他更喜欢 ArgumentNullException 而不是 NullReferenceException

MSDN 提到 NullReferenceException:

The exception that is thrown when there is an attempt to dereference a null object reference.

ArgumentNullException they 上说:

The exception that is thrown when a null reference (Nothing in Visual Basic) is passed to a method that does not accept it as a valid argument.

回答者好像说你可以用。

有什么理由或任何情况我应该选择一个而不是另一个吗?

P.S.

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

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

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

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 被抛出,调用者只会看到

Object reference not set to an instance of an object

没有这个意义(使用检查时):

Value cannot be null. Parameter name: s

即使是看起来会抛出 NullReferenceException 而不是抛出 ArgumentNullExceptions:

的框架扩展方法
List<string> list = null;
var results = list.Select(x => x); //ArgumentNullException

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

NullReferenceException 从不 故意按照约定 抛出。它表示无意的预定义违规。因此,它几乎总是表示错误。该错误在引发异常的代码中。

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

使用Argument*Exception表示您拒绝传递的参数。 NullReferenceException表示抛出该异常的代码的程序员出错了

NullReferenceException 视为运行时提供的失败断言。 Argument*Exception 表示 "I thought about this case and I consciously reject it.".