当存在内部异常时,是否有理由保留外部异常?

时间:2015-09-04 18:20:59

标签: c# exception

如果发现异常并且存在内部异常,那么是否有人知道为什么可能需要引用该包装异常的原因?我无法想到一个,但想要仔细检查。

3 个答案:

答案 0 :(得分:3)

绝对。外部异常在技术上是完整堆栈跟踪的容器,对于复杂的调试方案很有用。这是一个非常虚构的例子(不太复杂)来解释我的意思。

假设您有一个非常通用的日志库,允许您配置日志记录属性(如日志目标为db,file,...)。可以在实例化Logger对象时完成配置,但也可以基于Logger.Log(...)调用覆盖。 Logger不验证配置,它只是最好记录数据并在无法完成时抛出异常。

现在假设您有一个使用上述库的应用程序。该应用程序使用IoC来实例化记录器的全局实例,IoC正确设置默认配置,这样使用这些配置设置始终完美。在应用程序的各个位置,应用程序的某些部分进行.Log(...)调用,但覆盖记录器配置,其中一些工作,以及其他导致异常被抛出的配置。假设这个应用程序是由抛弃包装异常的人编写的,只报告内部最常见的异常。

在上面的场景中,并非完全不切实际,如果仅考虑内部异常,那么当日志记录失败时,我们会在尝试使用日志记录库进行日志时知道它失败了,但可能没有足够的信息来知道在消费应用程序中进行了日志记录尝试。另一方面,如果我们有外部异常,我们可以简单地检查它以确定错误源自应用程序的位置。使调试变得更容易。

答案 1 :(得分:1)

当然。调试问题时,任何信息都可以提供帮助。内部异常通常只包含完整堆栈的一小部分。通常,包装异常会添加语义信息。

例如,Entity Framework异常会告诉您有关EF概念的非常具体的事情。但是,它们也可以让您进入InnerException以获得SqlException

从.NET 4.5开始SqlException通常有一个相当无意义的Win32Exception作为内部异常。你当然不想依赖"文件未找到"无法通过网络访问SQL Server实例时。 (这是一个真实的例子。)

为什么要丢弃错误信息?!

如果您想使用处理错误的内部异常,那么只需遍历异常链并选择您感兴趣的异常。

答案 2 :(得分:1)

当要求对象在某些上下文中执行委托时,会发生涉及嵌套异常的常见情况。在许多这样的情况下,各种因素可能会阻止对象以预期的方式执行委托;通常会通过抛出异常来表示无法执行委托。另一方面,虽然执行委托也可能抛出几乎任何可能引发此类原因的异常,但委托抛出的异常几乎总是与调用对象抛出的异常处理不同,并且必须因此可以与它们区分开来。

一个常见的补救措施是,在调用的委托中抛出的任何异常都会导致调用对象抛出一种特殊的异常,并且该异常将委托的对象作为{{1 }}。如果委托抛出外部代码希望处理的异常,外部代码将经常捕获包装器异常,而不会对其堆栈跟踪或其他任何内容感兴趣,但会使用外部异常的存在来确定内部代码委托抛出异常而不是调用它的对象。

当从一个异常中清除的尝试最终触发另一个异常时,会发生嵌套异常的另一个更困难的情况。例如,当程序生成应该写入文件的数据时发生异常。在从该异常中展开时,程序会尝试关闭该文件(根据需要将待处理数据提交到磁盘),但该操作也会失败。在这种情况下,两种例外都可能非常重要。即使预期第一个例外,数据未写入磁盘这一事实也可能是一个不容忽视的问题。不幸的是,前三种面向对象语言/框架(C ++,Java或.NET)中没有一种真正有办法处理这种情况。