.NET如何针对不同类型的异常进行捕捉?

相信阅读本文的园友都已经养成了try-catch的习惯,但对于异常的捕捉和处理可能并不在意。确实,直接捕捉所有异常的基类:Exception 使得程序方便易懂,但有时这样的捕捉对于业务处理没有任何帮助,对于特殊异常应该采用特殊处理能够更好地引导规划程序流程.

下面的代码演示了一个对于不同异常进行处理的示例:


public class Program
{
    public static void Main(string[] args)
    {
        Program p = new Program();
        p.RiskWork();

        Console.ReadKey();
    }

    public void RiskWork()
    {
        try
        {
            // 一些可能会出现异常的代码
        }
        catch (NullReferenceException ex)
        {
            HandleExpectedException(ex);
        }
        catch (ArgumentException ex)
        {
            HandleExpectedException(ex);
        }
        catch (FileNotFoundException ex)
        {
            HandlerError(ex);
        }
        catch (Exception ex)
        {
            HandleCrash(ex);
        }
    }

    // 这里处理预计可能会发生的,不属于错误范畴的异常
    private void HandleExpectedException(Exception ex)
    {
        // 这里可以借助log4net写入日志
        Console.WriteLine(ex.Message);
    }

    // 这里处理在系统出错时可能会发生的,比较严重的异常
    private void HandlerError(Exception ex)
    {
        // 这里可以借助log4net写入日志
        Console.WriteLine(ex.Message);
        // 严重的异常需要抛到上层处理
        throw ex; 
    }

    // 这里处理可能会导致系统崩溃时的异常
    private void HandleCrash(Exception ex)
    {
        // 这里可以借助log4net写入日志
        Console.WriteLine(ex.Message);
        // 关闭当前程序
        System.Threading.Thread.CurrentThread.Abort();
    }
}

(1)如代码所示,针对特定的异常进行不同的捕捉通常很有意义,真正的系统往往要针对不同异常进行复杂的处理。

异常的分别处理是一种好的编码习惯,这要求程序员在编写代码的时候充分估计到所有可能出现异常的情况,当然,无论考虑得如何周到,最后都需要对异常的基类Exception进行捕捉,这样才能保证所有的异常都不会被随意地抛出。

(2)除此之外,除了在必要的时候写try-catch,很多园友更推荐使用框架层面提供的异常捕捉方案,以.NET为例:

  • WinForm,可以这样写:AppDomain.CurrentDomain.UnhandledException +=new UnhandledExceptionEventHandler(UnhandledExceptionFunction);

  • ASP.NET WebForm,可以在Application_Error()方法里捕获异常

  • ASP.NET MVC,可以写ExceptionFilter

  • ASP.NET WebAPI,可以写ExceptionHandler