2013-10-20 55 views
4

如果可能在finally块中引发异常,如何传播这两个异常 - 从catch和finally?C#中传播抛出finally块的异常而不丢失catch块的异常的最佳做法是什么?

作为一个可能的解决方案 - 使用AggregateException:

internal class MyClass 
{ 
    public void Do() 
    { 
     Exception exception = null; 
     try 
     { 
      //example of an error occured in main logic 
      throw new InvalidOperationException(); 
     } 
     catch (Exception e) 
     { 
      exception = e; 
      throw; 
     } 
     finally 
     { 
      try 
      { 
       //example of an error occured in finally 
       throw new AccessViolationException(); 
      } 
      catch (Exception e) 
      { 
       if (exception != null) 
        throw new AggregateException(exception, e); 
       throw; 
      } 
     } 
    } 
} 

这些异常可以像下面的代码片段进行处理:

private static void Main(string[] args) 
{ 
    try 
    { 
     new MyClass().Do(); 
    } 
    catch (AggregateException e) 
    { 
     foreach (var innerException in e.InnerExceptions) 
      Console.Out.WriteLine("---- Error: {0}", innerException); 
    } 
    catch (Exception e) 
    { 
     Console.Out.WriteLine("---- Error: {0}", e); 
    } 

    Console.ReadKey(); 
} 
+1

我想不出一个有意义的场景,它有必要知道这两个例外。你的解决方案肯定会工作,但在调用者处理它将非常复杂。 – dasblinkenlight

+0

我认为在最后(在finally catch块中)重新抛出永远不会被达到,因为如果发生异常,对象* e *永远不会* null *。 – pasty

+4

如果您遇到异常情况,您说“我知道如何解决这个问题” - 如果事实证明您不知道如何解决此问题,那么您需要尽可能少地做以掩盖错误情况。 –

回答

3

由于意见建议这可能表示“很遗憾”结构化代码。例如,如果您经常发现自己处于这种情况,那么可能表明您正在尝试在您的方法中做太多事情。你只想抛出异常,如果没有别的东西可以做(你的代码被卡住了,你无法编程的问题,你只想捕获一个异常,如果有合理的期望你可以做一些有用的事情。在框架中有一个OutOfMemoryException,但很少有人会试图捕捉它,因为大部分它意味着你被绑定:-)

如果finally块中的异常是在try块中是异常的,返回这个异常只会使实际问题变得复杂或模糊,从而导致难以解决。在极少数情况下,如果有返回的异常原因(例如异常),那么使用AggregateException即可。但是在采取这种方法之前,问问自己是否有可能将异常分离为可以返回并单独处理单个异常的单独方法。

+0

同意,在使用此类解决方案之前,应修改代码的设计。我试图找到更多的存储方式,而不是使用finally块来执行“try-catch with empty catch block”。 –

+0

要添加到@ Dweeberly的答案,通常使用finally块来做任何资源清理。结构良好的代码不会尝试在finally块中执行任何恢复或进一步处理。最后是作为最后的努力,让你的代码在异常传播到堆栈之前有最后一个镜头。正如谚语所说的“以强大的力量来承担巨大的责任”,明智地使用“终于” –

+0

@AbhijeetPatel:某些类进入清理需要可能失败的行为的状态是正常的(例如,可以构造一个'File '类,其中每个写数据方法将确保数据在返回之前被写入,但与使用延迟写入的类相比,性能会非常糟糕)。通常,'finally'中的故障比'try'中的故障更严重,但很难知道在任何特定情况下是否会出现这种情况。 – supercat

相关问题