请参阅下文,了解正在进行的操作
我有一个非常奇怪的问题,捕获的异常是null。
代码使用MEF并努力报告组合错误。使用调试器我可以看到抛出异常(InvalidOperationException
)但是当它被下面代码中的最后一个catch块捕获时,ex
变量为null。在调试器和正常执行代码时都是如此。
static T ResolveWithErrorHandling<T>() where T : class
{
try
{
IocContainer.Compose(Settings.Default.IocConfiguration);
return IocContainer.Resolve<T>();
}
catch (ReflectionTypeLoadException ex)
{
// ... special error reporting for ReflectionTypeLoadException
}
catch (Exception ex)
{
// ex is null - that should not be possible!
// ... general error reporting for other exception types
}
return null;
}
我用注释替换的代码是格式化错误消息的非常简单的代码。那里没什么奇怪的。
我试图改变代码以发现可能产生的影响:
ReflectionTypeLoadException
),则最终catch块中捕获的异常不再为null。InvalidOperationException
添加一个catch块作为第一个catch块,则该块中捕获的异常不为null。InvalidOperationException
添加一个catch块,则该块中捕获的异常为null。项目使用Code Contracts并对编译器生成的代码进行后处理以检查合同。不幸的是,在没有对项目进行大手术的情况下,我没有想出办法摆脱测试目的。
我目前的解决方法是不捕获ReflectionTypeLoadException
,而是在常规异常处理程序中分支ex
的类型。
这种“不可能”行为的解释是什么?什么是ReflectionTypeLoadException
catch block?
令人尴尬的是,异常不为空,并且根据C#标准15.9.5不能为空。
但是,在项目can mess up the display of local variables in the debugger中使用代码约定,因为编译器生成的IL代码可以通过代码约定重写,因此最终的IL与调试信息稍微不同步。在我的例子中,ex
变量显示为null,即使它不是。在应用程序终止之前发生的错误报告的不幸性质意味着我认为由于ex
为空而ex.Message
在NullReferenceException
内部抛出ex
而导致错误报告未被调用抓住了。使用调试器,我能够“验证”ReflectionTypeLoadException
为空,除非它实际上不为空。
{{1}}的catch块似乎影响调试器显示问题,这使我的困惑更加复杂。
感谢所有回复的人。
答案 0 :(得分:12)
刚遇到同样的问题。我终于发现我用同样的名字捕获了不同的异常,就像你做的那样:
catch (ReflectionTypeLoadException ex)
{
// ...
}
catch (Exception ex)
{
// ex is not null!
// ...
}
两者都被命名为'ex'。更改其中一个名称可以解决这个问题,例如:
catch (ReflectionTypeLoadException reflectionEx)
{
// ...
}
catch (Exception ex)
{
// ex is null - that should not be possible!
// ...
}
答案 1 :(得分:5)
我遇到了同样的问题。在我的情况下,重命名异常变量(例如ex =&gt; ex1)允许我捕获任何异常......
答案 2 :(得分:4)
您应该检查IocContainer是否在某个时刻捕获Exception ex
抛出ex.InnerException
而不检查它是否为空。
C#愉快地接受throw null
,最终在catch (Exception)
。
答案 3 :(得分:4)
我遇到了同样的问题。在调试器中查看时异常为null,即使正在捕获正确类型的异常 - UpdateException。我可以通过打开Exception Assistant来查看异常。
一旦我关闭“执行运行时合同检查”,就会捕获不再为空的异常。我一直在积极地使用代码合同进行一年,并且在我最近在这个特定项目中开始使用EF 4.1之前没有看到这个问题 - 但我不知道EF是否是关于捕获异常的控制变量是null
答案 4 :(得分:1)
异常实际上不是null,这是调试器的问题。 代码契约(ccrewrite)会更改IL操作码并扰乱调试器,因为leave.s操作码会转换为leave操作码。 这两个操作码具有不同的大小和指令地址更改,这就是当异常名称相同时调试器丢失的原因。
您可以在调试器中使用$ exception来解决此问题。
答案 5 :(得分:0)
我也有同样的情况。它恰好是Eclipse调试器的一个bug。 (实际上,这种情况只能是某些调试器错误的结果。)
Eclipse重启就足够了 - 运行时异常变得正常,而不是null。其他调试器可能不那么友好。