异常处理类

问题描述:

什么是异常处理,而不必把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(); 
    } 
} 

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

的思考?

+1

通过在你的'ExceptionHandler'类中重新抛出异常,你将失去先前的堆栈跟踪。 – 2011-04-06 22:45:56

+0

有没有办法保存堆栈跟踪? – 2011-04-06 22:52:18

+2

用'throw;'替换'throw e;'' – 2011-04-06 22:53:03

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

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

但接下来呢?

每一种异常需要进行不同的处理。 ExceptionHandler怎么会知道该怎么做?你可以尝试多种方式,例如,以解决这个问题:

  1. ExceptionHandler派生,并把代码中的虚拟方法来处理异常
  2. 通过一些Action<Exception>实例的处理程序,并让它调用现在你需要创建一个全新的类各try块,并覆盖了一堆的方法的东西糟糕比你结束了:以前正确的一个

解决方案(1)会比你有什么更糟糕之前(不是我)立即清楚特定类中的代码如何适合程序的流程)。这也会让另一个重要问题得不到解决:您可能需要上下文(访问当前范围中的变量)来正确处理异常。你将如何提供访问这个上下文?解决方案(2)实际上最终会非常类似于编写我们想要避免的catch块(每个Action实际上将是catch块的内容)。我们最终只会以更复杂和冗长的方式做同样的事情。

也有其他的问题:

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

至于ExceptionThrower ...它可能提供什么好处,而不是throw new Exception();

异常处理已经非常复杂,并且很难在不添加额外齿轮的情况下正确处理。特别是如果他们不给你买任何新东西的话。 不要这样做。

+0

以一个简单的控制台应用程序为例 - 如果我在执行UI的Main()方法中有一行代码,并且试图捕获它,那么不会在应用程序中发生任何异常,直到该catch块?或者我错过了什么?为什么我需要超过单一的try/catch? – 2011-04-06 22:54:51

+2

@SeanThoman:因为有些例外可以合理预期(例如试图打开一个文件,你可能会得到一个'FileNotFoundException')以及意味着游戏结束的异常(例如'ExecutionEngineException')。你无法从同一个地方合理地回应;你需要不同的上下文。 – Jon 2011-04-06 22:59:06

+0

我认为你可以通过配置处理类的逻辑,但它可能太复杂,并引入自己的错误,如你所说。如果这是一个非基于UI的应用程序,那该怎么办呢?只是一个工作应用程序按顺序执行一些进程,完全放手,管理员只需定期检查日志以确保事情顺利进行。你不希望应用程序停止运行某些例外,等等。 – 2011-04-06 23:07:56

OK,这可能不是你想要我通常对一般的异常处理类的想法过敏的答案,但...

。你几乎可以听到它本身就是一个矛盾。例外情况是例外事件。异常事件不能在一般的方式来处理,但需求量身定制的操控无论他们在哪里出现,这基本上意味着你的代码应该有两点:

  1. 是防守有关,以避免在例外的任何输入首先
  2. try..catch无论是有意义捕捉和处理异常(注意,这意味着,你不应该在所有的方法try..catch块)

那么,捕捉和处理异常的意义何在?简而言之,您的代码具有能够处理异常的知识。如果没有,请让异常向上调用。 只有我认为你应该捕获所有异常,并在你的应用程序的顶层有一些通用的默认行为。这通常是UI。

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

根据您的安排,您必须处理所有异常,只知道它们是哪种类型的异常。您不再知道异常实际发生的位置,因此除了记录日志或向用户显示消息之外,您无法对此问题进行任何操作。此外,try/catch块通常还包含一个finally块,在这个块中,即使抛出异常(如关闭流等),也可以确保事情发生。你在处理这件事的安排上没有任何办法。

适当的异常处理可能会非常棘手,并且没有任何灵丹妙药可以使它变得简单明了。如果有的话,.Net将已经合并它。

+0

您可以通过使用堆栈跟踪来了解它发生的位置......但我确实看到了您的观点。由于使用'throw e'会破坏堆栈跟踪,而只使用'throw'只能在catch块中使用,所以似乎很棘手..您必须记录堆栈跟踪或编程地在堆栈跟踪之前执行某些操作E”。 – 2011-04-06 23:00:48

+0

你的意思是如果你写了一个堆栈跟踪解析器(yay!),你可以推断出现异常的地方。没错,但是你仍然需要在某处放置代码,以便对特定的异常类型和位置信息做出适当的响应。为什么不把它放在正常的catch块中,就在导致问题的代码的下面? – MusiGenesis 2011-04-06 23:05:04

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

为什么你的代码中有这么多的try-catch块?你能举一些例子吗?异常的性质“非常”,即不那么频繁!你不仅应该经常捕捉异常,而且每个异常都是不同的,并且在一种情况下工作的相同样板代码可能不适用于许多其他情况。没有人说异常处理很容易(或者生成紧凑的代码) - 你应该认为仔细关于你需要捕捉异常并适当处理它的每种情况 - 避免捕捉你不需要处理的异常。

+0

我实际上没有那么多尝试抓块......但我很好奇这个想法。 – 2011-04-06 23:05:21