为什么NullReferenceException不包含有关什么是null的信息?

NullReferenceException后面的devise决定是否包含除基类数据(如堆栈跟踪)之外的任何运行时特定信息? 有没有Visual Studio的扩展,可以直接告诉你expression式的哪一部分是空的?

NRE是一个非常低级的例外。 当要求从低于64K的地址读取数据时,处理器产生硬件exception(“陷阱”)。 虚拟内存空间的这个区域总是未被映射,特别是陷阱指针错误。 它作为一个AccessViolation启动,当地址小于0x00010000时,CLR变为NRE。 在这一点上,exception的上下文很less,所有已知的是导致陷阱的机器码指令的地址。

将机器代码指令地址反向devise回程序中的指定variables是不可能的。 以这种方式工作非常重要,否则抖动将不得不产生非常低效的代码。 所有可以合理完成的事情都是恢复源代码行号。 这需要包含行号信息的debugging信息(.pdb)。 CLR知道如何读取.pdb文件并使用它来生成exception的堆栈跟踪。 但是,由于JIT优化器执行的优化,这通常仍然不准确,因此会移动代码。 您只会得到一个debugging版本的保证匹配。 发布版本的PDB不包含源行号信息的原因。 你可以改变这一点。

这个问题有一个很简单的解决scheme。 自己检查null并在运行时执行之前生成自己的exception。 testing相当便宜,远低于一纳秒。

您可以设置Visual Studio来立即抛出NullReferenceException ,而不是第一次在catch块。

  • debugging
  • 例外
  • 通用语言
  • 运行时exception系统
  • System.NullReferenceException(检查框)

那么你将在导致NullReferenceException的行中有一个中断。

在运行时确定什么是空的没有简单的方法 – 必要的信息将不得不从IL中反编译和推断出来,这是足够低级的,所有它知道的是“堆栈顶部的项目是空的“但不是那个项目到了那里。

(我不知道这样的扩展,但这将是一个很好的debugging器增强)

NullReferenceException由运行时引发,而不是由语言引发。 运行时不知道引用来自哪里; 它只知道一条指令试图使用空引用。

事实上,这个exception“很可能”是由本地窗口“无效访问冲突”SEHexception造成的,它被运行时捕获,并被翻译成ILexception(“很可能”:我没有检查过是否是这种情况,这是我的猜测是什么是最好的代码执行的方式)。

并非所有关于您的代码的信息在运行时都可用。 例如,局部variables名称不可用。 所以,不可能像“局部variablesmyObj为null,但是它的成员已被调用”那样引发exception。 此外,在运行时有很多非用户编写的对象(例如,为闭包/匿名types/迭代器生成的类),这也可能是空引用exception的来源。

如果您有debugging符号,则可以跟踪导致exception的行。 如果它很简单,你会直接得到你的null值。 否则(想想a.Value = b.Do(c.GetX(),d.GetY(z.ToString())); )你必须debugging你的IDE