. net捕获的异常意外为空

本文关键字:意外 异常 net | 更新日期: 2023-09-27 17:50:18

如下所示

我有一个非常奇怪的问题,捕获的异常是null。

代码使用MEF并努力报告组合错误。使用调试器,我可以看到异常被抛出(一个InvalidOperationException),但是当它被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;
}

我用注释替换的代码实际上是格式化错误消息的简单代码。没有什么奇怪的。

我已经尝试修改代码,以发现可能产生的影响:

  • 如果我删除第一个捕获块(ReflectionTypeLoadException),在最后一个捕获块中捕获的异常不再为空。
  • 如果在第一个catch块中捕获另一种异常类型,则在最后一个catch块中捕获的异常不再为空。
  • 如果我为InvalidOperationException添加捕获块作为第一个捕获块,在该块中捕获的异常不为空。
  • 如果我在两个catch块之间添加InvalidOperationException的catch块,则在该块中捕获的异常为null。

项目使用Code Contracts,编译器生成的代码经过后处理来检查契约。不幸的是,我还没有找到一种方法,可以在不对项目进行大手术的情况下摆脱测试目的。

我目前的解决方法是不捕获ReflectionTypeLoadException,而是在通用异常处理程序中对ex的类型进行分支。

这种"不可能"的行为的解释是什么?ReflectionTypeLoadException捕获块是怎么回事?


令人尴尬的是,异常不是null,而且根据c#标准15.9.5,它不能为null。

然而,在项目中使用代码契约可能会弄乱调试器中局部变量的显示,因为编译器生成的IL代码可以被代码契约重写,因此最终的IL与调试信息略有不同步。在我的例子中,ex变量显示为空,即使它不是。不幸的是,错误报告发生在应用程序终止之前,这意味着我认为错误报告不会被调用,因为ex为空,ex.Message在catch块中抛出NullReferenceException。使用调试器,我能够"验证"ex是空的,除了它实际上不是空的。

我的困惑是由ReflectionTypeLoadException的catch块似乎影响调试器显示问题的事实。

感谢所有回应的人。

. net捕获的异常意外为空

刚刚遇到了同样的问题。我终于发现我捕获了相同名称的不同异常,就像您所做的那样:

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!
    // ...
}

我遇到了同样的问题。在我的情况下,重命名异常变量(例如ex => ex1)允许我捕获任何异常…

您应该检查是否在某些时候,IocContainer捕获Exception ex抛出ex.InnerException而不检查它是否为空。

c#欣然接受throw null,并以catch (Exception)结束。

我遇到了同样的问题。当在调试器中查看异常时,该异常为空,即使捕获了正确类型的异常——UpdateException。我可以通过打开exception Assistant来查看异常。

一旦我关闭"执行运行时契约检查"捕获的异常不再为空。我已经积极地使用代码契约一年了,在我最近开始在这个特殊的项目中使用EF 4.1之前还没有看到这个问题——但是我不知道EF是否是一个控制变量,关于捕获的异常为null。

异常实际上不是null,这是调试器的问题。代码契约(ccrewrite)改变了IL操作码,这扰乱了调试器,因为离开了。S操作码被转换成左操作码。两个操作码有不同的大小和指令地址变化,这就是为什么当异常名称相同时调试器丢失的原因。

你可以在调试器中使用$exception来解决这个问题。

我也遇到过同样的情况。它碰巧是Eclipse调试器的一个错误。(实际上,这种情况可能只是某些调试器错误的结果。)

Eclipse重启是足够的-运行时异常变为正常,而不是null。