C#:不覆盖当前活动的一个

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功能并自动调用。

+0

正如你可以控制代码'bar'包装在try/catch块所以外面只能看到由'foo'抛出的异常。 –

您需要手动编写这样的:

// 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

+0

正如我写的,不幸的是,我可以控制的唯一代码是'bar()'内的一个代码,其他一切都是库用户的责任... –

+0

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