或许你在ViusalStudio调试程序的时候,发现Output windows打印出了一行信息,关于A first chance exception of type'System.NullReferenceException' occurred,可能你曾经疑惑,什么是firstchance exception,这句话是否说明我的code有问题,但是如果有问题,为什么我的程序没有抛出任何异常,只是在Output windows显示了这么一条信息呢,如果我不去看output window,可能根本就发觉不到这个信息。
这里来说一说什么是firstchance exception,当你在VS调试程序的时候,当程序有问题的时候,是Debugger(也可以理解为VS本身)先捕获到了这个异常,在这个时候,VS要决定如何去解决这个问题。
- 是现在停下来,把这个问题抛出来,弹出一个对话框,告诉用户你的程序这里有个问题,让用户决定是继续运行还是停止。
- 还是不去管,听之任之,如果用户有try catch捕获到的话,让用户自己的代码去处理,如果没有try catch,让Runtime运行时去捕获到,然后让运行时去处理。但是在调试的时候,依然是VS进行二次捕获。
那么VS依靠什么去决定如何处理?在Debug设置下,如果勾选上CLR Exception,那么VS捕获到异常,不仅仅是在Output windows打印出消息,而且还会弹出对话框通知用户。
如果这里没有勾选,那么VS不作任何处理,就像没有这回事一样。
举个例子来说,像下面的代码,
如果VS捕获到并且抛出,程序就会停止在36行并且通知用户。如果VS听之任之,那么程序就会跳转到39行继续执行代码的处理逻辑。
需要明白2个概念,C#程序在真正运行的时候,是Runtime运行时作为最上层的管理者,exception最高会抛到这里。而在VS中调试的时候,是VS Runtime是作为最上层的管理者,exception最高会抛到这里让VS去通过对话框的形式通知用户。first chance exception会通过弹出框通知用户,如果用户选择Continue,那么程序是可以继续运行的。但是如果代码没有相应的捕获机制去处理,再次抛到了VS Runtime,捕获到,那么这就叫做second chance exception,这时候会再次有对话框弹出,但是这次代码就无法继续运行了。
而且还有一点需要注意,就是如果我们没有勾选上边的选项,如果在调程序的时候,VS会在39行抛出异常对话框。
但是如果我们勾选了,就会在52行异常真正发生的地方抛出异常对话框。
有人就要问,那么到底我是否应该勾选呢?这个还是要具体问题具体分析,如果你的项目引用了像NHibernate这样的重量级工具,那么这个DLL本身就很有可能很多地方会抛出异常,但是DLL本身有try catch去处理,如果你勾选了,catch代码块处理前,VS会捕获到,然后通知用户,这种情况会非常多,造成的结果就是用户要点很多Continue的对话框。这时候就不要勾选了。
参考链接:
https://blogs.msdn.microsoft.com/davidklinems/2005/07/12/what-is-a-first-chance-exception/
http://dzimchuk.net/post/when-a-first-chance-exception-of-type-xxx-occurred-you-really-have-a-bug