当前位置:  开发笔记 > 后端 > 正文

抛出NullReferenceException时检测目标对象是什么

如何解决《抛出NullReferenceException时检测目标对象是什么》经验,为你挑选了2个好方法。

我确信我们在某个时间或某个时间都收到了非常模糊的"对象引用未设置为对象的实例"异常.识别出问题的对象通常是设置断点和检查每个语句中的所有成员的繁琐任务.

有没有人有任何技巧可以通过编程手段或其他方式轻松有效地识别导致异常的对象?

- 编辑

看起来我像模样异常=).关键是_不必调试应用程序以找到错误的对象.编译器/运行时确实知道该对象已被分配/声明,并且该对象尚未被实例化.有没有办法在捕获的异常中提取/识别这些细节

@ W. Craig Trader

您的解释是设计问题的结果可能是我能得到的最佳答案.我对防御性编码非常强迫,并且在经过一段时间修复我的习惯之后设法摆脱了大部分这些错误.其余的只是把我调整到最后,并引导我将这个问题发布给社区.

谢谢大家的建议.



1> Craig Trader..:

在抛出NRE的点上,没有目标对象 - 这是异常的点.您最希望的是捕获发生异常的文件和行号.如果您在识别哪个对象引用导致问题时遇到问题,那么您可能需要重新考虑编码标准,因为这听起来就像您在一行代码上做得太多了.

这种问题的更好解决方案是通过内置语言结构或通过库来设计合同.DbC建议预先检查任何传入的参数,以获取超出范围数据的方法(即:Null)并抛出异常,因为该方法不适用于错误数据.

[编辑以匹配问题编辑:]

我认为NRE描述会误导你.CLR所具有的问题是,当对象引用为Null时,它被要求取消引用对象引用.以此示例程序为例:

public class NullPointerExample {
  public static void Main()
  {
    Object foo;
    System.Console.WriteLine( foo.ToString() );
  }
}

当你运行它时,当它试图评估foo上的ToString()方法时,它会在第5行抛出NRE.没有要调试的对象,只有未初始化的对象引用(foo).有一个类和一个方法,但没有对象.


回复:Chris Marasti-Georg的回答:

你永远不应该自己抛出NRE - 这是具有特定含义的系统异常:CLR(或JVM)试图评估未初始化的对象引用.如果您预先检查对象引用,则抛出某种无效的参数异常或特定于应用程序的异常,但不抛出NRE,因为您只会混淆必须维护您的应用程序的下一个程序员.



2> Matt Ryan..:

正如一些答案所指出的,告诉Visual Studio在Throw上打破NullReferenceException.

如何在未处理的异常被抛出时告诉VS中断

调试菜单| 例外(或Ctrl+ Alt+ E)

深入研究公共语言运行时异常

钻入系统

找到System.NullRefernceException,并在抛出此异常时选中Break,而不是允许它继续执行任何Catch块到位

所以现在当它发生时,VS将立即中断,并且Current Statement行将位于评估为null的表达式上.

此工具对各种异常都很有用,包括自定义异常(可以添加完全限定的类型名称,VS将在调试时匹配它)

这种方法的一个缺点是,如果在调试器中加载了代码,这些代码遵循了抛出和捕获大量异常的错误做法,在这种情况下,它会变回干草堆/针头问题(除非你可以修复那个代码 - 当然你已经解决了两个问题:)


可能派上用场的另一个技巧(但仅限于某些语言)是使用When(或等效)关键字...在VB中,这看起来像

Try
  ' // Do some work           '
Catch ex As Exception When CallMethodToInspectException(ex)

End Try

这里的技巧是在将callstack展开到Catch块之前评估When表达式.因此,如果您正在使用调试器,则可以设置该表达式的断点,如果查看callstack窗口(Debug | Windows | Callstack),您可以查看并导航到触发异常的行.

(您可以选择从CallMethodToInspectException返回false,因此Catch块将被忽略,运行时将继续通过堆栈搜索适当的Catch块 - 这可以允许不影响行为的日志记录,并且开销更少而不是抓住并重新投掷)


如果您只对非交互式日志记录感兴趣,那么假设您已经获得了Debug构建(或者在某种程度上,因为您已经处理了优化问题,使用PDB发布版本),您可以获得追踪所需的大部分信息来自Exception ToString的错误,包含stack-trace-with-line-number.

但是,如果行号不够,则可以通过提取异常的StackTrace(使用上述技术或仅在catch块中)来获取列号(因此非常多,特定的本地或表达式为null)本身):

int colNumber = new System.Diagnostics.StackTrace(ex, true).GetFrame(0).GetFileColumnNumber();

虽然我没有看到它对NullReference或其他运行时生成的异常的作用,但也可能有兴趣将Exception Hunter视为静态分析工具.

推荐阅读
和谐啄木鸟
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有