C# 异常处理

来源:互联网 发布:nodejs调用python脚本 编辑:程序博客网 时间:2024/06/09 20:47

一、异常的定义

     异常就是程序中的运行时错误,当出现异常时,系统会捕获这个错误并抛出一个异常。若程序没有提供处理该异常的代码,系统会挂起这个程序。

二、异常处理语句:try语句

1、作用:指明可能发生异常的代码块,并提供代码处理异常。

2、组成

(1)try块:将可能引发异常的代码用try块包围起来。try关键字告诉编译器:开发者认为块中的代码有可能引发一个异常;如果真的引发了异常,那么某个catch块就要尝试处理这个异常。

(2)catch子句:包含处理异常的代码,有如下三种形式的代码

        @1:catch (ExceptionType e){}   //带对象的特定catch子句

        @2:catch (ExceptionType){}    // 特殊catch子句,匹配任何该类型名称的异常

        @3:catch {}  //一般catch子句或泛化catch块或常规catch块

        说明:@1、特定catch子句即第一种形式的catch子句可以有多个,但必须按照从最具体到最不具体的顺序排列。

                 @2、常规catch块必须在所有catch块的后面。

       补充:常规catch块,等价与获取object数据类型的catch块,例如catch(object exception){...}。由于所有类最终都是从object派生,所以常规catch块必须出现在最后。

       常规catch块很少用,因为没有办法捕捉有关异常的任何信息。除此之外,c#不允许引发object类型的异常,只有使用c++这样的语言写的库才允许任意类型的异常。

       但在c#2.0中,假如遇到用另一种语言写的代码,而且它会引发不是从System.Exception类派生的异常,那么该异常对象会被包装到一个System.Runtime.CompilerServices.RuntimeWrappedException(是从System.Exception派生的)中。换言之,在c#程序集中,所有异常(无论他们是否从System.Exception派生)都会表现得和从System.Exception派生的一样。所以用于捕捉System.Exception的catch块会捕捉之前的块没有捕捉到的所有异常,同时,System.Exception catch块之后的一个常规catch块永远得不到调用。所以,在c#2.0中,假如在捕捉System.Exception的catch块之后添加了一个常规catch块,编译器就会报告一条警告信息,指出常规catch块永远都不会执行。

(3)finally块:在所有情况下都要执行,无论有无异常发生,即使try块中有return语句,finally块也总是会在返回到调用代码之前执行。

注意:try语句中try块是必需的,catch块和finally块必需有一个或两个都有。若两个都有,那么finally块必须放在最后。

三、为异常寻找处理代码的过程

(1)BCL定义了许多类,每个类代表了一个指定的异常类型。当异常发生时,CLR首先创建给类型的异常对象,然后,寻找适当的catch子句处理异常。

(2)若异常在一个没有被try语句保护的代码中产生或若try语句没有匹配的catch子句,系统将按顺序搜索调用栈,寻找匹配的处理代码。

例子:  method2()                                       method1()                                                调用栈

     {........                                                   {  ............                                                       method2()

          try {...}                                                     try{...method2().......}                                method1()

          catch.......                                                catch..............                                           ...........

          finally.......                                               finally.........                                                 ...........

     }                                                             }

      假设异常发生在method2 内部的try块内部。

  系统会:查看method2是否有处理该异常的catch块:@1、有,method2处理异常,程序继续执行。@2、没有,系统沿着调用栈找到method1,搜寻适当的catch块。 若method1有合适的catch子句,系统将会回到栈顶(那里是method2)执行method2的finally块并把method2弹出栈,然后执行method1的catch子句和finally子句。若method1没有适当的catch子句,系统会继续搜索调用栈。

四、常见异常的类型

 System.Exception    最泛化的异常,其他所有异常类型都从它派生。

System.ArgumentException:  传给方法的一个参数无效。

System.ArgumenNullException: 一个不应该为null的参数为null。

System.ApplicationException: 一个自定义的应用程序异常,开发者可以用它标识特殊的非致命的应用程序错误。

 

System.FormatException:参数格式不符合调用的方法的参数规范。

System.IndexOutOfRangeException:试图访问一个不存在的数组元素。

System.InvalidCastException: 因无效的类型转换或显示转换引发的异常。

System.NotImplementdeException:虽然找到了方法签名,但该方法尚未完全实现。

System.NullReferenceException: 试图访问尚未包含任何数据的一个变量(一般是调用其值为null的一个对象的成员是引发)。

System.ArithemeticException: 发生了一个无效的数学运算,但其中不包括被零除。

System.ArrayTypeMismatchException:试图将类型有误的元素存储到数组中。

System.StackOverFlowException:通常意味着一个无限循环,方法不停地回调自身(成为递归)。

 

异常对象常见属性:

string Message:含有解释异常原因的消息

string StackTrace:含有描述异常发生在何处的信息

Exception InnerException:若当前异常是由另一个异常引起的,此属性包含前一个异常的引用

 

五、使用throw语句使代码显示地引发一个异常

两种形式:

     throw  ExceptionObject;在try块中使用,执行throw语句后,try块中在throw语句之后的语句跳过不执行

     throw;仅在catch语句中使用。重新抛出当前异常,系统继续它的搜索,寻找另外的catch块。

示例:

 例1:static void main()                                                                  

{

   try                                                                                               

  {

             Console.WriteLine("begin  executing");

             Console.WriteLine("throw exception");

             throw new Exception ("Arbitrary exception");

             Console.WriteLine("end executing ");

   }

    catch( FormatException exception)

   { Console.WriteLine("a FormatException was thrown");        throw;//重新引发一个异常}

     catch( Exception exception)

   { Console.WriteLIne ("Unexception error:{0}",exception.Message );}

     catch         {Console.WriteLIne("unexcepted error!")}

  Console.WriteLine("shutting  down ....")

}

输出结果:

begin executing

throw exception

Unexception error:Arbitrary exception

shutting  down.......//这个程序没有finally块,所以它随后会执行try/catch块之后的System.Console.WriteLine()语句。

 

注意:避免使用异常处理来处理预料之中的情况

           开发者应尽量避免为预料之中的情况或正常的控制流引发异常。例如,开发者事先就应该预料到用户可能在输入年龄的时候输入无效的文本。所以,不要用异常来验证用户输入的数据。相反,开发者应该在尝试转换数据类型之前就对数据进行检查(甚至可以考虑从一开始就防止用户输入无效的数据)。异常是专为跟踪例外的,事先没有预料的,而且可能造成严重后果的情况设计的。未预料之中的情况使用异常,会造成你的代码难以阅读,理解和维护。除此之外,c#在抛出异常时会产生些许性能损失。

原创粉丝点击