2015-09-04 79 views
2

如果发现异常并且存在内部异常,是否有人知道为什么该包装异常可能需要引用任何东西?我想不出一个,但想要仔细检查。当存在内部异常时,有没有理由保持外部异常?

+2

有很多原因。为什么你认为它是无用的?就我个人而言,我尽量避免用另一个异常来包装异常,除非它添加有用的信息。因此,我几乎不希望他们被忽略。 –

+0

我的印象是,如果SQL Server在调用中抛出一个错误,并且在泛型异常中捕获到该错误,那么内部异常就是抛出的异常,并且它被包装在我的catch块中的泛型异常中。在这种情况下,我只需传递相关的内部异常,而不必保留通用包装器创建的运行时。 –

回答

1

当某个对象被要求在某些上下文中执行委托时,会出现涉及嵌套异常的常见情况。在许多这样的情况下,可能有各种因素可能阻止对象以预期的方式执行委托;通常会通过抛出异常来指示无法执行委托。另一方面,虽然几乎所有可能为这种原因抛出的异常也可能由正在执行的委托抛出,但由委托抛出的异常几乎总是应该与调用对象抛出的异常处理不同,并且必须从而与他们区分开来。

一个常见的解决办法是说,从被调用的委托中抛出的任何异常都会导致调用对象抛出一种特定类型的异常,并且该异常将使委托对象成为InnerException。如果代理抛出了一个外部代码希望处理的异常,那么外部代码通常会捕获包装器异常而不会对其堆栈跟踪或其他任何东西感兴趣,但会使用外部异常的存在来确定内部委托抛出异常,而不是调用它的对象。

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

1

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

例如,实体框架异常告诉你很多关于EF概念的具体事情。但他们也让你达到InnerException获得SqlException

从.NET 4.5开始SqlException通常有一个相当没有意义的Win32Exception作为内部异常。当无法通过网络访问SQL Server实例时,您肯定不希望依赖“未找到文件”。 (这是一个真实的例子。)

为什么要扔掉错误信息?

如果你想利用内部异常的为处理错误,则只是走的异常链,并选择您感兴趣的例外。

3

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

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

现在假设您有一个使用上述库的应用程序。应用程序使用IoC来实例化记录器的全局实例,并且IoC正确设置默认配置,以便使用这些配置设置始终可以正常工作。在应用程序的各个地方,应用程序的某些部分会调用.Log(...)调用,但会覆盖记录器配置,其中一些配置有效,其他配置会导致引发异常。假设这个应用程序是由抛出包装异常并仅报告内部大多数异常的人编写的。

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