【问题标题】:NullReferenceException vs ArgumentNullExceptionNullReferenceException 与 ArgumentNullException
【发布时间】:2016-09-15 20:57:16
【问题描述】:

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

MSDN 提到 NullReferenceException

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

ArgumentNullException they 说:

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

回答者似乎说你可以使用任何一个。

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

附言

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

【问题讨论】:

  • 我应该选择一个而不是另一个你的意思是你应该扔哪个,或者你应该让哪个发生?
  • stackoverflow.com/questions/463302/… 的问题非常相似,stackoverflow.com/questions/463302/… 的答案与此问题相关。
  • 你也不能使用。 NRE 必须保留给那些实际上因取消引用 null 而死的程序。您使用 ArgumentNullException 来防止它们在 NRE 上摔倒。告诉客户端程序员“我知道你做错了,请永远不要传递 null”。 NRE 不会发送如此精美的消息,当它被抛出时,您无法确定它是您的错误还是库的错误。
  • @DaveShaw 我应该扔哪个,我的问题很广泛:S

标签: c# exception nullreferenceexception


【解决方案1】:

如果您在代码中明确抛出异常,则应选择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 被抛出,调用者只会看到

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

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

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

【讨论】:

  • 什么是CLR
  • @Chax 公共语言运行时。基本上是每个 .NET 程序的“幕后”实现
【解决方案2】:

NullReferenceException从不按照惯例故意抛出。它表示无意的预编码违规。因此,它几乎总是发出错误信号。错误在引发异常的代码中。

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

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

NullReferenceException 视为运行时提供的失败断言。 Argument*Exception 的意思是“我考虑过这个案子,我有意识地拒绝了它。”。

【讨论】:

    【解决方案3】:

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

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-02-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多