2

如果我的 try 抛出,并且 finally 抛出,我怎样才能在一个链中保持这两个异常,以便我可以让它们自然地在堆栈中传播,而不需要中间的日志记录工具?

我认为这可能会有所帮助:

Exception exCause = null;
try {
    // do something risky
} catch ( Exception ex ) {
    exCause = ex;
    throw;
} finally {
    //check for an important error condition
    // if error: throw new ApplicationException("finally failed", exCause);
}

但我不确定它是否会破坏框架中的某些内容。

显然,如果我在 finally 中调用引发异常的东西,它仍然存在无法合并的两个预先存在的异常的问题,但我认为这可能有助于减轻系统中每个库的需求可以访问相同的跟踪例程。

4

3 回答 3

3

finally最好通过以不会引发异常的方式编写处理程序来避免这种情况。

于 2013-03-26T15:55:04.593 回答
3

也许你可以看看 System.AggregateException 类

AggregateException 用于将多个故障合并到一个可抛出的异常对象中。

http://msdn.microsoft.com/en-us/library/system.aggregateexception.aspx

这可能会帮助你

于 2013-03-26T15:52:15.447 回答
1

C++、Java 和 .Net 历来都没有提供任何处理堆栈展开清理代码中出现的异常的好方法。这是不幸的,因为在许多情况下,发生在清理代码中的异常对程序的行为比发生在主行代码中的异常更重要,但对诊断目的帮助不大(特别是因为可能会发生清理异常由于主线异常)。

在 VB.net 中可以编写一个 try/finally 块,这样finally代码将知道什么异常(如果有)导致代码离开该try块,而无需声称捕获或处理有问题的异常。不幸的是,这在 C# 中是不可能的,尽管 C# 中的代码可以通过调用用 vb.net 编写的包装器来实现这种效果;即使在 vb.net 中,使用这样的包装器也可能会有所帮助,因为实现正确语义所需的代码有点恶心。如果两种语言中的using块可以使用类似的接口,则可以改进,如果在堆栈展开期间执行异常IDisposableDuringException { void Dispose(Exception ex);},则会调用该接口。Dispose这将允许代码在Dispose方法将提供的异常包含在它可能抛出的任何异常中,并且还会根据是否抛出异常而产生处置行为的可能性(例如,如果事务范围通过异常退出,则应该清楚地执行回滚——这就是毕竟它们的重点——但要求它们在通过正常方式退出时隐式执行回滚是 icky)。

关于如果在finally清理过程中抛出异常会发生什么,我建议无论异常是否挂起,正确的行为应该是抛出类似 custom 的东西CleanupFailureException。即使调用代码已经准备好捕获例如InvalidOperationException从主线抛出的内容,主线的成功完成以及随后的InvalidOperationException清理期间也可能代表与代码准备处理的情况不同的情况,并且应该因此使用不同的异常类型。

顺便说一句,关于代码是否应该假定意外异常是致命的还是非致命的,经常存在一些争论。我认为在许多情况下,正确的方法是让堆栈从意外异常中展开,明确地使正在使用的对象无效,这样所有未来对这些对象的操作都会导致异常。这将产生这样的效果,如果一个意外的异常可能破坏一个至关重要的对象,程序可能会在造成任何损害之前就死掉,但同时允许如果一个异常破坏了一个无论如何都不需要的对象的可能性(例如,如果在从损坏的文件加载文档时发生意外问题,并且在尝试加载文档时与之关联的数据结构被彻底破坏,

于 2013-03-26T16:36:52.713 回答