C#:不覆盖当前活动的一个
以下面的最小示例抛出异常:C#:不覆盖当前活动的一个
try { foo }
finally { bar() }
foo
可以或可以不丢,并且bar()
可以或可以不丢。 如果两个函数都抛出,则bar()
抛出的异常将覆盖foo
抛出的异常。但是,我需要看看foo
引发的异常情况。我可以控制的唯一代码是bar()
。 在C++中,可以通过在bar()
内检查std::uncaught_exceptions
来实现。 C#怎么样?
有a check using Marshal.GetExceptionPointers(),但作为回答状态,这是一个可怕的黑客,在我的情况下,它是不够的,因为我的代码需要在Mono运行,在没有实现该功能。
语境:
在我的现实生活中的案例,foo
是由图书馆用户提供,可能会抛出各种异常的一大块代码,并bar()
是由我提供的Dispose
功能并自动调用。
您需要手动编写这样的:
// Whether an exception has been thrown from the main block.
bool hasMainException = false;
try
{
foo();
}
catch
{
// Record that exception has been thrown from main block, and rethrow.
hasMainException = true;
throw;
}
finally
{
// Execute secondary block within its own try-catch block.
try
{
bar();
}
catch
{
// Only rethrow exception from secondary block if there isn't
// already an exception from the main block.
if (!hasMainException)
throw;
}
}
顺便说一句,我需要达到非常相似,涉及Dispose
方法,可以把你的用例的东西,所以我写了一些扩展方法来实现这一目标,以及支持所有用例的各种策略。见DisposableExtensions
和DisposeExceptionStrategy
。您感兴趣的策略是Subjugate
。
正如我写的,不幸的是,我可以控制的唯一代码是'bar()'内的一个代码,其他一切都是库用户的责任... –
@mic_e:你是对的;我错过了。除了你提到的破解之外,我不相信这是可以做到的。 – Douglas
这将
- 遥
foo
异常,即使异常被抛出bar
。 - 如果从
foo
没有发生异常,则从bar
中抛出异常。 - 如果没有引发异常,则不抛出任何东西。
-
保留来自任一异常的原始堆栈跟踪。
ExceptionDispatchInfo exceptionInfo = null; try { foo(); } catch(Exception ex) { exceptionInfo = ExceptionDispatchInfo.Capture(ex); } finally { try { bar(); } catch(Exception ex) { exceptionInfo = exceptionInfo ?? ExceptionDispatchInfo.Capture(ex); } } exceptionInfo?.Throw();
正如你可以控制代码'bar'包装在try/catch块所以外面只能看到由'foo'抛出的异常。 –