为什么NullReferenceException比CLR中的任何其他异常更昂贵?

时间:2016-09-22 05:02:01

标签: c# nullpointerexception clr

在寻找null check vs捕获NullReferenceException时,我遇到了这个。

  

捕获空取消引用是CLR可以执行的最昂贵的操作之一,如果您的代码抛出大量NullReferenceExceptions,这可能会对性能产生严重影响。测试nullity并对其做一些其他事情(甚至抛出异常!)是一种更便宜的操作。

     

以下是我找到问题的链接。 When is handling a null pointer/reference exception preferred over doing a null check?

我想知道如何捕获NullReferenceException比null check和抛出异常更昂贵。

[因为声誉数字不足而无法评论]

2 个答案:

答案 0 :(得分:8)

这里的要点不是NullReferenceException比任何其他例外都贵。抛出异常的代价来自展开堆栈,这更多地取决于调用结构而不是特定异常。我相信文档试图提出的一点是,首先要安全防范异常,而不是在抛出异常时处理异常。

答案 1 :(得分:2)

NullReferenceException 硬件异常 ,它首先由Windows Page Fault处理程序进行处理。此操作需要kernel context switch,这可能是非常昂贵的操作,具体取决于基础CPU硬件以及操作系统安全模型。此外,垃圾收集器通常必须暂停某些操作,直到上下文切换完成为止。由于GC为所有线程和应用程序域提供服务,因此任何时候GC暂停使用都会导致潜在的重大性能下降,而这种下降只会在意外的间隔内出现。

通过比较,通过throw关键字从C#中引发您自己的异常会生成 软件异常 。它们不需要特殊的处理,并且在异常的catch处理程序是本地的(在同一函数内)的情况下,可以进一步优化,因为不需要额外的展开来发现适当的catch处理程序。这就是MSDN文档建议不要依赖NullReferenceException的原因。

由于存在太多变量,因此很难给出具体的性能差异值。在最坏的情况下,我可以想象它可能会慢近一个数量级-例如,能够在处理单个硬件异常时抛出并捕获一百个本地软件异常。在实践中,尽管我猜性能比大约在3:1到10:1之间,这取决于CPU,OS,C#CLR和共享Heap / GC的活动线程数。