【发布时间】:2011-08-04 18:50:35
【问题描述】:
请参阅下文了解正在发生的事情
我有一个非常奇怪的问题,即捕获的异常为空。
代码使用 MEF 并努力报告组合错误。使用调试器,我可以看到异常被抛出(InvalidOperationException),但是当它被下面代码中的最后一个 catch 块捕获时,ex 变量为空。在调试器和正常执行代码时都是如此。
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;
}
我用 cmets 替换的代码是格式化错误消息的非常简单的代码。没有什么奇怪的事情发生。
我已尝试更改代码以发现可能产生的影响:
- 如果我删除第一个 catch 块 (
ReflectionTypeLoadException),则在最后一个 catch 块中捕获的异常不再为 null。 - 如果我在第一个 catch 块中捕获另一个异常类型,则在最后一个 catch 块中捕获的异常不再为 null。
- 如果我为
InvalidOperationException添加一个catch 块作为第一个catch 块,则在该块中捕获的异常不为空。 - 如果我在两个 catch 块之间为
InvalidOperationException添加一个 catch 块,则在该块中捕获的异常为 null。
项目使用Code Contracts,编译器生成的代码经过后处理以检查合约。不幸的是,为了测试目的,我还没有想出一种方法来摆脱这种情况,而无需对项目进行大手术。
我目前的解决方法是不捕获ReflectionTypeLoadException,而是在通用异常处理程序中分支ex 的类型。
对这种“不可能”的行为有何解释? ReflectionTypeLoadException 捕获块是怎么回事?
令人尴尬的是,异常不是 null,而且根据 C# 标准 15.9.5,它不能为 null。
但是,在项目can mess up the display of local variables in the debugger 中使用代码契约,因为编译器生成的 IL 代码可以被代码契约重写,因此最终的 IL 与调试信息略有不同步。在我的情况下,ex 变量即使不是也显示为 null。在应用程序终止之前发生错误报告的不幸性质意味着我相信错误报告不会被调用,因为ex 为空并且ex.Message 在我的catch 块中抛出NullReferenceException。使用调试器,我能够“验证”ex 为空,但它实际上不为空。
ReflectionTypeLoadException 的 catch 块似乎会影响调试器显示问题,这使我更加困惑。
感谢所有回复的人。
【问题讨论】:
-
真的有
ReflectionTypeLoadException被扔到任何地方吗? -
只是一个注释,但您能否处理不同类型的异常,或者您是否只报告每种异常?如果这是通用报告并且您无法处理异常,那么我不确定您是否需要确定捕获范围。
-
当您为 InvalidOperationExecption 添加捕获时会发生什么?
-
@Jaymz:是的,如果组合中包含的程序集无法加载。异常包含一些额外的信息,可以帮助解决问题,这些信息在 catch 块中提取。
-
看起来
catch (ReflectionTypeLoadException ex)行吃掉了异常......
标签: c# exception-handling mef code-contracts