如果我的尝试抛出,并且我终于抛出,我怎么能在单个链中保留两个异常,以便我可以让它们自然地向上传播而不需要中间日志记录工具?
我认为这可能会有所帮助:
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中抛出异常的东西,它仍然存在两个预先存在的异常无法合并的问题,但我认为这可能有助于减轻对每个库的需求一个可以访问相同跟踪例程的系统。
答案 0 :(得分:3)
也许您可以查看System.AggregateException类
AggregateException用于将多个失败合并到一个可抛出的异常对象中。
http://msdn.microsoft.com/en-us/library/system.aggregateexception.aspx
这可能会对你有所帮助
答案 1 :(得分:3)
最好通过编写finally
处理程序以避免抛出异常来避免这种情况。
答案 2 :(得分: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
清理期间抛出异常会发生什么,我会建议无论异常是否挂起,正确的行为应该是抛出类似自定义的CleanupFailureException
。即使调用代码已准备好捕获例如从主线抛出的InvalidOperationException
,在清理过程中成功完成主线后跟InvalidOperationException
可能代表的情况与代码准备处理的情况不同,因此应该使用一个不同的例外类型。
顺便说一句,关于代码是否应该假设意外异常是致命或非致命的,通常会有一些争论。我认为在许多情况下,正确的方法是使堆栈从意外异常中展开,明确地使正在使用的对象无效,这样所有将来使用这些对象的操作都将导致异常。这样做会产生这样的效果:如果一个意外的异常可能会破坏一个非常重要的对象,程序可能会在造成任何损害之前死掉,但同时允许一个异常破坏一个无论如何都不需要的对象的可能性(例如,如果在从受损文件加载文档时发生意外问题,并且在尝试加载文档时,与其关联的数据结构被无可救药地损坏,那么如果代码可以放弃部分加载的文档而没有它,那么这样做是明智的腐败不一定影响其他任何事情。