C#:抛出异常而不覆盖当前活动的异常

时间:2017-07-06 21:38:50

标签: c# exception mono

采用以下最小例子:

try { foo }
finally { bar() }

foo可能会或可能不会投掷,而bar()可能会或可能不投掷。 如果两个函数都抛出,则bar()抛出的异常将覆盖foo抛出的异常。但是,我需要查看foo引发的异常。我能控制的唯一代码是bar()内部。 在C ++中,可以通过选中std::uncaught_exceptions内的bar()来实现。 C#怎么样?

a check using Marshal.GetExceptionPointers(),但正如答案所述,这是一个可怕的黑客攻击,在我的情况下它是不够的,因为我的代码需要在Mono上运行,而Mono没有实现该功能。

上下文:

在我的实际案例中,foo是一个由库用户提供的大块代码,可能会抛出各种异常,而bar()Dispose函数这是由我提供并自动调用的。

2 个答案:

答案 0 :(得分:0)

您需要手动编码:

// 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方法的用例,因此我写了一些扩展方法来实现这一点,以及支持所有用例的各种策略。请参阅DisposableExtensionsDisposeExceptionStrategy。您感兴趣的策略是Subjugate

答案 1 :(得分:0)

这将

  • foo引发异常,即使bar中引发了异常。
  • 如果bar没有例外,则
  • foo引发例外。
  • 如果没有引发异常,
  • 不会抛出任何东西。
  • 保留原始堆栈跟踪中的任何一个异常。

        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();