异常处理类

本文关键字:异常处理 | 更新日期: 2023-09-27 17:49:33

处理异常而不必到处放置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(); 
    }
}

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

想法吗?

异常处理类

在产品代码中看到类似的设计实际上是有一个很好的理由的。

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

但是接下来呢?

每个异常都需要以不同的方式处理。ExceptionHandler如何确切地知道该做什么?你可以尝试用多种方法来解决这个问题,例如:

  1. 继承ExceptionHandler,并将处理异常的代码放在虚拟方法中
  2. 传递一些Action<Exception>实例给处理程序,并让它调用适当的一个

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

解决方案(2)实际上与编写我们一直想要避免的catch块非常相似(每个Action将有效地成为catch块的内容)。我们最终做了同样的事情,只是以一种更复杂和冗长的方式。

还有其他问题:

  • 如果ExceptionHandler不能处理异常,应该怎么做?再次抛出它将导致你失去原来的堆栈跟踪,实际上破坏了那里所有好的信息。
  • 如果ExceptionHandler有bug怎么办?您可以信任try/catch。你能同样信任自己写的代码吗?

对于ExceptionThrower…它比throw new Exception();有什么好处呢?

异常处理已经是一件复杂的事情,如果不给机器增加额外的齿轮,就很难把它处理好。尤其是他们不给你买新东西的时候。别这样。

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

我通常对通用异常处理类的想法很反感。你几乎可以听到它本身是一个矛盾。异常是一个异常事件。异常事件不能以一般方式处理,而是需要在它们出现的地方进行定制处理,这本质上意味着您的代码应该做两件事:

  1. 对任何输入进行防御,以避免首先出现异常
  2. try..catch放在捕获和处理异常有意义的地方(注意,这意味着您不应该在所有方法中使用try..catch块)

那么,捕获和处理异常在哪里有意义呢?简而言之,您的代码具有使其能够处理异常的知识。如果没有,让异常向上冒泡到调用者。only的地方我认为你应该捕捉所有异常并有一些通用的默认行为,它在你的应用的顶层,这通常是UI。

对不起,这不是一个好主意。当您在代码中使用围绕相关部分的正常try/catch块捕获异常时,您可以使用两个关键信息来处理该问题:异常的类型,以及异常发生的位置

在你的安排下,你必须处理所有的异常,只知道它们是什么类型的异常。您不再知道异常实际发生在哪里,因此除了将其记录下来或向用户显示一条消息外,您实际上无法对问题做任何事情。

此外,try/catch块通常还包括finally块,在其中您可以确保即使抛出异常(如关闭流等)也会发生事情。在你的安排中,你没有办法处理这件事。

正确的异常处理可能很棘手,没有什么灵丹妙药能让它变得简单直接。如果有的话,. net早就把它合并了。

我们的代码库中有一个类,它的签名与您提出的签名非常相似,现在我可以告诉您,它只带来了痛苦和痛苦!

为什么你的代码中有那么多try-catch块?你能举几个例子吗?异常的本质是"异常",也就是说不那么频繁!你不仅不应该频繁地捕捉异常,而且每个异常都是不同的,在一种情况下工作的相同的样板代码可能不适用于许多其他情况。

没有人说异常处理是容易的(或产生紧凑的代码)-你应该仔细考虑关于你需要捕获异常的每种情况,并适当地处理它-避免捕获你不需要处理的异常。