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

Ego*_*hin 70 c#

除了基类数据(如堆栈跟踪)之外,NullReferenceException背后的设计决策是什么,不包含任何运行时特定的信息?是否有Visual Studio的扩展,可以直接告诉你表达式的哪一部分为空?

Han*_*ant 70

NRE是一个非常低级别的例外.当处理器要求从64K以下的地址读取数据时,处理器会生成硬件异常("陷阱").虚拟内存空间的该区域始终未映射,特别是捕获指针错误.它以AccessViolation开始,当地址小于0x00010000时由CLR变为NRE.此时,异常的上下文非常少,所有已知的是导致陷阱的机器代码指令的地址.

将机器代码指令地址反向设计回程序中的命名变量是不可能的.重要的是它以这种方式工作,否则抖动必须生成非常低效的代码.可以合理地做的就是恢复源代码行号.这需要包含行号信息的调试信息(.pdb).CLR知道如何读取.pdb文件并使用它来生成异常的堆栈跟踪.但是,由于JIT优化器执行的优化,它通常仍然不准确,它会移动代码.您只能获得Debug构建的保证匹配.Release版本的PDB不包含源行号信息的原因.你可以改变它.

这个问题有一个非常简单的解决方案 在让运行时执行此操作之前,请自行检查null并生成您自己的异常.测试非常便宜,远小于纳秒.

  • 我当然希望不是.如果这很容易的话,我将失去一份好工作. (13认同)
  • 在错误消息中提供全面的信息是计算机科学的一个有价值的目标.我希望有一天,无论是语言还是计算机都改变到"将一切都包含在一个保护条款中"并不是最好的答案. (3认同)
  • @HansPassant .NET 4.6.2显然允许您在发生NRE时查看哪个表达式为"null".知道怎么可能这样可能吗?https://blogs.msdn.microsoft.com/dotnet/2016/08/02/announcing-net-framework-4-6-2/ (3认同)
  • 我要打电话给BS.我们可以得到NRE的行号,这不是机器码,而是低级别的逆向工程.此时的堆栈跟踪生成应该至少能够为您提供生成异常的语句. (2认同)

Mar*_*erl 26

您可以将Visual Studio设置为NullReferenceException立即中断Throw,而不是先在catch块中中断.

  • 调试
  • 例外
  • 通用语言
  • 运行时异常系统
  • System.NullReferenceException(选中复选框)

然后你将在线上休息,导致NullReferenceException.


Kir*_*oll 5

没有什么简单的方法可以确定运行时什么是null - 必须从IL中反编译和推断出必要的信息,这是足够低级的,它只知道"堆栈顶部的项目为空" "但不是那个项目如何到达那里.

(我不知道这样的扩展,但它将是一个很好的调试器增强功能)