【Basic Code】异常处理再认识

来源:互联网 发布:linux remount什么意思 编辑:程序博客网 时间:2024/05/17 04:16

      今天下午工作上没有事,看了一会书,对于try catch的使用之前的一个不理解的地方,做一下更正,记录下来。

      一直在用的就是catch异常,而对于throw异常不是很熟悉,通过几个例子,就搞清楚了,如下:

public static void PrintArg(string arg){try{if (arg == null){ArgumentNullException myEx = new ArgumentNullException("arg");                        //抛出一个ArgumentNullException类型的异常,这里是主动抛出的异常                       throw myEx;}Console.WriteLine(arg);}catch (ArgumentNullException e){Console.WriteLine("Message: {0}", e.Message);}}static void Main(){string s = null;PrintArg(s);PrintArg("Hi there!");Console.ReadKey();}
       如上所示,在PrintArg()这个方法中,catch中写的要捕获的异常类型为:ArgumentNullException,在try块中抛出的异常类型也为ArgumentNullException,正好被catch块捕获。

      


     不带异常对象的抛出

public static void PrintArg(string arg){try{try{if (arg == null){ArgumentNullException myEx = new ArgumentNullException("arg");throw myEx;}Console.WriteLine(arg);}catch (ArgumentNullException e){Console.WriteLine("Message: {0}", e.Message);//重新抛出异常,没有附加参数 -- 这种形式重新抛出当前异常,系统继续他的搜索,寻找另外的处理代码。throw;}}catch{Console.WriteLine("Outer Catch: Handing an Exception.");}}static void Main(){string s = null;PrintArg(s);//PrintArg("Hi there!");Console.ReadKey();}
       这里在try块里又嵌套了一个try catch,重新throw出的异常,被外层的catch块捕捉。

     

     经过这两个例子,对于throw的使用就基本上了解差不多了,下面来看看原理上的东西,仍然是一个例子:

class Program{    static void Main()    {        MyClass MCls = new MyClass();        try        { MCls.A(); }        catch (DivideByZeroException)        { Console.WriteLine("catch clause in Main()"); }        finally        { Console.WriteLine("finally clause in Main()"); }        Console.WriteLine("After try statement in Main.");        Console.WriteLine("              --- keep running");    }}class MyClass{    public void A()    {        try        { B(); }        catch (System.NullReferenceException)        { Console.WriteLine("catch clause in A()"); }        finally        { Console.WriteLine("finally clause in A()"); }    }    void B()    {        int x = 10, y = 0;        try        {            x /= y;        }        catch (System.IndexOutOfRangeException)        { Console.WriteLine("catch clause in B()"); }        finally        { Console.WriteLine("finally clause in B()"); }    }}
     代码执行效果:

       

      分析,为什么代码这样子执行?

      问题在于,这里的异常类型是DivideByZeroException,方法B中catch语句捕获的异常类型为:IndexOutOfRangeException,于是乎,向上寻找跳到A方法中,发现A方法中捕获的异常类型为NullReferenceException,不能捕获,再次向上寻找,到Main方法当中,catch的异常类型为DivideByZeroException,捕获异常,但是这时候,代码会先将B方法和A方法的finally语句走完,也就是为什么在Console中输出的内容先是:

      finally clause in B()

      finally clause in A()

      然后才是:catch clause in Main();


      这里多个层次调用try catch涉及到堆栈的一些知识,如图(上个例子的解释):

                                       

      另外,向外throw的异常,如果在方法中都未能进行捕获的话,编译器会顺着向下的方法到其他方法中寻找能够捕获的catch子句,直至throw出来的Exception被抓,此所谓天网恢恢啊。

      又一个月,时间好快。






0 0