【问题标题】:Could this `if` statement generate a Null-Reference Exception ever?这个“if”语句会生成空引用异常吗?
【发布时间】:2011-02-26 14:44:32
【问题描述】:

我认为我的观点很明确,在任何情况下,这会引发空引用异常吗?即在尝试访问其 Count 属性时反对 e.Result 为空。

if (e.Result == null || e.Result.Count == 0)
    return;

编辑:为了充分了解这个问题(对于后来的提问者),我们将如何防止该异常发生,我们可以使用lock 语句吗?怎么样?

【问题讨论】:

  • 后两个问题的答案是(1)是的,(2)视情况而定。假设您构建了正确的锁并设法在不崩溃的情况下获得“计数”。然后你解锁结果,它会变异为有一个不同的计数。 你打算如何处理你刚刚成功捕获的现在不准确的计数? 用不正确的计数做任何事情似乎很危险。为多线程场景提供一般建议是没有意义的;给我们一个现实的场景,我们可以提供建议。

标签: c# if-statement nullreferenceexception logical-operators


【解决方案1】:

仅当方法不是线程安全的时,该代码才会抛出 NullReferenceException。这意味着,如果另一个线程决定在您的 e.Result == null 检查之后和您的 e.Result.Count == 0 检查之前的确切时刻巧合地将 null 分配给 e.Result

【讨论】:

  • @marcind 是的,但问题是关于e.Result 而不是e 本身。
【解决方案2】:

只有当 e 为 null 时才会这样做。

【讨论】:

    【解决方案3】:
    e == null
    

    多线程和竞争条件?

    【讨论】:

    • e 不能是 null,因为它是一个事件处理程序,而不是手动调用。
    • @LordCover 仅仅因为变量被命名为e 并不意味着它是一个事件处理程序:)
    • @marcind,我知道 :),但我是这里的开发人员,我告诉你,它来自事件处理程序。
    【解决方案4】:

    如果Result 背后有自己的代码并且该代码因该错误而失败,它可能会抛出“Null-Reference Exception”。

    【讨论】:

      【解决方案5】:

      没有。 - e.Result ==null 将首先被评估,如果为真则 return 将立即被调用并且不会评估第二种情况。线程可能不同

      【讨论】:

      • 不考虑多线程,我以为是这样的。
      【解决方案6】:
                  EventArgs args = e;
                  if (args.Result == null || args.Result.Count == 0)
                  {
                      return;
                  }
      

      这个想法是您首先将事件 args ( e ) 复制到您自己的本地元素中,并将其用于 if 条件检查。请注意确保副本的深度足以复制结果(否则,当另一个线程刚刚在 if 检查中途将结果归零时,您仍然最终会遇到多线程情况)。本地副本始终是线程安全的。

      【讨论】:

      • 但是本地副本是对原始副本的引用,对吗?它会受到应用在其原始对象上的影响。
      • 它不会受到一些更改引用'e'的代码的影响(例如,一些外部代码'e = null'不会将本地副本args设置为null)但肯定会受到影响通过在“e”中操作“结果”的代码(例如,如果外部代码运行“e.Result = null”,那么这肯定会将本地副本的 Result 也设置为上面的 null)..这就是为什么我添加了备注:确保进行深拷贝(我上面的代码可能没有反映深拷贝,但就是这样)
      • 为什么不复制 e.Result 呢?
      【解决方案7】:

      除了其他人已经指出的多线程/竞争条件问题之外,您可能正在寻找的主题是 short-circuit evaluation 在 C# 中,|| 运算符使用短路(与渴望的 | 相反),因此如果 e.Result == null 评估为 true,则不会评估 e.Result.Count == 0

      其他人已经回答了,但我想给你这种行为的名称和一些进一步的阅读。

      【讨论】:

        猜你喜欢
        • 2012-01-09
        • 1970-01-01
        • 2015-06-30
        • 1970-01-01
        • 1970-01-01
        • 2015-05-17
        • 2020-08-22
        • 2022-07-22
        • 1970-01-01
        相关资源
        最近更新 更多