异常处理类

Sea*_*man 3 c# exception-handling try-catch rethrow

处理异常的最佳实践是什么,而无需在任何地方放置try/catch块?

我有创建一个致力于接收和处理异常的类的想法,但我想知道它是否是一个好的设计理念.这样的类会收到异常然后根据其类型或错误代码决定如何处理它,甚至可以解析堆栈跟踪以获取特定信息等.

以下是背后和实施的基本思想:

public class ExceptionHandler
{
    public static void Handle(Exception e)
    {
        if (e.GetBaseException().GetType() == typeof(ArgumentException))
        {
            Console.WriteLine("You caught an ArgumentException.");
        }
        else
        {
            Console.WriteLine("You did not catch an exception."); 
            throw e;   // re-throwing is the default behavior
        }
    }
}

public static class ExceptionThrower
{
    public static void TriggerException(bool isTrigger)
    {
        if (isTrigger)
            throw new ArgumentException("You threw an exception.");
        else
            Console.WriteLine("You did not throw an exception."); 
    }
}

class Program
{
    static void Main(string[] args)
    {
        try
        {
            ExceptionThrower.TriggerException(true); 
        }
        catch(Exception e)
        {
            ExceptionHandler.Handle(e);  
        }
        Console.ReadLine(); 
    }
}
Run Code Online (Sandbox Code Playgroud)

我认为这将是一个有趣的尝试,因为理论上你只需要在main()方法调用周围需要一个或很少的try/catch块,并让异常类处理其他所有内容,包括重新抛出,处理,记录等等.

思考?

Fre*_*örk 6

好的,这可能不是你想要的答案,但......

我通常对一般异常处理类的想法过敏.你几乎可以听到它本身就是一个矛盾.例外是特殊事件.特殊事件无法以一般方式处理,但需要在任何可能出现的地方进行定制处理,这实际上意味着您的代码应该有两件事:

  1. 对任何输入都要防守,以避免一开始就出现异常
  2. try..catch块放在任何有意义的地方捕获和处理异常(注意这意味着你不应该try..catch在所有方法中都有块)

那么,捕获和处理异常在哪里有意义?简而言之,您的代码具有使其能够处理异常的知识.如果没有,请将异常气泡向上呼叫给呼叫者.我认为你应该捕获所有异常的唯一地方,并且在应用程序的顶层有一些通用的默认行为.这通常是UI.


Jon*_*Jon 5

其实有一个很好的理由,为什么你没有看到在生产代码类似的设计.

首先,这样的设计无法帮助您减少代码中的try/ catch对数量(这应该是显而易见的).它可以帮助您减少catch给定的语句数量try,因为您可以捕获System.Exception并转发到ExceptionHandler...

但接下来呢?

每个例外都需要以不同的方式处理.怎么会ExceptionHandler知道该怎么做?您可以尝试以多种方式解决此问题,例如:

  1. 派生ExceptionHandler并放置代码来处理虚拟方法中的异常
  2. 将许多Action<Exception>实例传递给处理程序并让它调用正确的实例

解决方案(1)会比以前更糟糕:现在你需要为每个try块创建一个全新的类,并覆盖一堆方法,最终得到比以前更糟糕的东西(现在还不清楚代码如何一个特定的类适合你的程序流程).它还会留下另一个未回答的重要问题:您可能需要上下文(访问当前范围中的变量)来正确处理异常.您将如何提供对此上下文的访问权限?

解决方案(2)实际上最终会非常类似于编写catch我们一直希望避免的块(每个块Action实际上都是catch块的内容).我们最终只是以更复杂和冗长的方式做同样的事情.

还有其他问题:

  • ExceptionHandler如果无法处理异常应该怎么办?再次抛出会导致您丢失原始堆栈跟踪,实际上会破坏其中的所有良好信息.
  • 如果有错误ExceptionHandler怎么办?你可以使用try/ catch.你能相信你自己编写的代码达到同样的程度吗?

至于ExceptionThrower......它可能提供什么好处throw new Exception();呢?

异常处理已经是一个复杂的问题,如果不在机器上增加额外的齿轮就很难做到这一点.特别是如果他们不给你买任何新东西.不要这样做.

  • @SeanThoman:因为也有例外您可以合理预期(例如试图打开一个文件,你可能会得到一个`FileNotFoundException`),并且意味着结束的整个过程(例如'ExecutionEngineException`)例外.你无法从同一个地方合理回应两者; 你需要不同的背景. (2认同)