• 异常处理


    一、为什么需要处理异常

    二、异常的种类

    1.语法异常

    2.逻辑异常。比如10-2=22;

    3.编译异常。比如除数为0;

    三、如何处理异常

    try{} catch{} finnally{};

    四、几个案例

    案例一、

     1 class Program
     2     {
     3         static void Main(string[] args)
     4         {
     5             M1();
     6 
     7             Console.ReadKey();
     8         }
     9 
    10         static void M1()
    11         {
    12             try
    13             {
    14                 Console.WriteLine("===========");
    15                 //如果M2的catch中没有throw,把异常往外抛,M1根本不知道M2中出现了异常,这不合适。
    16                 M2();
    17                 
    18             }
    19             catch (Exception ex)
    20             {
    21 
    22                 Console.WriteLine(ex.Message.ToString());
    23             }
    24             finally
    25             {
    26                 Console.WriteLine("这是M1中的finally");
    27             }
    28 
    29             Console.WriteLine("============");
    30         }
    31 
    32         private static void M2()
    33         {
    34             try
    35             {
    36                 int m = 10;
    37                 int r = m / 0;
    38             }
    39             catch (Exception ex)
    40             {
    41                 Console.WriteLine(ex.Message.ToString());
    42                 //throw;//表示往外抛出异常,只有在catch中能这么写。
    43             }
    44             finally
    45             {
    46                 Console.WriteLine("M2中的finally代码");
    47             }
    48 
    49         }
    50     }
    View Code

    throw放到catch中表示把异常往外抛出。只能放在catch中,放在其他地方会报错。

    案例二、

     1  static void Main(string[] args)
     2         {
     3             T1();
     4 
     5             Console.ReadKey();
     6         }
     7 
     8         static void T1()
     9         {
    10             try
    11             {
    12                 Console.WriteLine("11111111111");
    13 
    14                 Console.WriteLine("^^^^^^^^^^^^^^^^^^^^^");
    15                 return;
    16                 Console.WriteLine("222222222222");
    17             }
    18             catch (Exception ex)
    19             {
    20                 Console.WriteLine("33333333333");
    21             }
    22             finally
    23             {
    24                 Console.WriteLine("444444444444444");
    25             }
    26 
    27         }
    View Code

    反编译后的IL代码:

     1 .method private hidebysig static void T1() cil managed
     2 {
     3     .maxstack 1
     4     .locals init (
     5         [0] class [mscorlib]System.Exception exception)
     6     L_0000: nop 
     7     L_0001: nop 
     8     L_0002: ldstr "11111111111"
     9     L_0007: call void [mscorlib]System.Console::WriteLine(string)
    10     L_000c: nop 
    11     L_000d: ldstr "^^^^^^^^^^^^^^^^^^^^^"
    12     L_0012: call void [mscorlib]System.Console::WriteLine(string)
    13     L_0017: nop 
    14     L_0018: leave.s L_003a
    15     L_001a: stloc.0 
    16     L_001b: nop 
    17     L_001c: ldstr "33333333333"
    18     L_0021: call void [mscorlib]System.Console::WriteLine(string)
    19     L_0026: nop 
    20     L_0027: nop 
    21     L_0028: leave.s L_002a
    22     L_002a: leave.s L_003a
    23     L_002c: nop 
    24     L_002d: ldstr "444444444444444"
    25     L_0032: call void [mscorlib]System.Console::WriteLine(string)
    26     L_0037: nop 
    27     L_0038: nop 
    28     L_0039: endfinally 
    29     L_003a: ret 
    30     .try L_0001 to L_001a catch [mscorlib]System.Exception handler L_001a to L_002a
    31     .try L_0001 to L_002c finally handler L_002c to L_003a
    32 }
    33 
    34  
    View Code

    可见,finally中的代码会执行,并且是在return之前执行。实际上,反编译后的代码return是在最后,我们看到的是编译器处理后的代码。

    案例二、

     1 class Program
     2     {
     3         static void Main(string[] args)
     4         {
     5             Console.WriteLine(T1());
     6 
     7             Console.ReadKey();
     8         }
     9 
    10         static int T1()
    11         {
    12             try
    13             {
    14                 Console.WriteLine("11111111111");
    15                 int m = 10, n = 0;
    16                 int r = m / n;
    17                 Console.WriteLine("^^^^^^^^^^^^^^^^^^^^^");
    18                 return 100;
    19                 
    20             }
    21             catch (Exception ex)
    22             {
    23                 Console.WriteLine("33333333333");
    24                 return 1000;
    25             }
    26             finally
    27             {
    28                 Console.WriteLine("444444444444444");
    29             }
    30 
    31         }
    View Code

    为何最后return1000?反编译后我们发现,程序在最开始声明了一个变量,return 100的时候,给变量赋值为100;return 1000的时候,又给变量赋值为1000;最后return这个变量。最后输出的结果为:111111

    333333

    4444444

    1000

    反编译后的代码:

     1 private static int T1()
     2 {
     3     int num4;
     4     try
     5     {
     6         Console.WriteLine("11111111111");
     7         int num = 10;
     8         int num2 = 0;
     9         int num3 = num / num2;
    10         Console.WriteLine("^^^^^^^^^^^^^^^^^^^^^");
    11         num4 = 100;
    12     }
    13     catch (Exception)
    14     {
    15         Console.WriteLine("33333333333");
    16         num4 = 0x3e8;
    17     }
    18     finally
    19     {
    20         Console.WriteLine("444444444444444");
    21     }
    22     return num4;
    23 }
    24 
    25  
    View Code

    案例三、

     1  class Program
     2     {
     3         static void Main(string[] args)
     4         {
     5             Console.WriteLine(T1());
     6 
     7             Console.ReadKey();
     8         }
     9 
    10         static int T1()
    11         {
    12             int result = 100;
    13             try
    14             {
    15                 result++;
    16                 return result;
    17                 
    18             }
    19             catch (Exception ex)
    20             {
    21                 result++;
    22                 return result;
    23             }
    24             finally
    25             {
    26                 result++;
    27             }
    28 
    29         }
    View Code

    结果为101;因为只要遇到return,不管这个变量是否与前面的变量名是否一样,都会声明一个新的变量,反编译后的代码是:新变量=result(不管怎样,会声明变量,如果有异常,赋值语句不会执行),在finally之后返回这个变量。

    反编译后的代码:

     1 private static int T1()
     2 {
     3     int num2;
     4     int num = 100;
     5     try
     6     {
     7         num++;
     8         num2 = num;
     9     }
    10     catch (Exception)
    11     {
    12         num++;
    13         num2 = num;
    14     }
    15     finally
    16     {
    17         num++;
    18     }
    19     return num2;
    20 }
    View Code

    案例四

     1 class Program
     2     {
     3         static void Main(string[] args)
     4         {
     5             Console.WriteLine(T1());
     6 
     7             Console.ReadKey();
     8         }
     9 
    10         static int T1()
    11         {
    12             int result = 100;
    13             try
    14             {
    15                 result++;
    16                 int x = 11, y = 0;
    17                 Console.WriteLine(x/y);
    18                 return result;
    19                 
    20             }
    21             catch (Exception ex)
    22             {
    23                 result++;
    24                 return result;
    25             }
    26             finally
    27             {
    28                 result++;
    29             }
    30 
    31         }
    View Code

    始终记住,try{}catch{}中的 return 变量/具体的值,等价于 新的变量=值,反编译后的代码是:新变量=变量(不管怎样,会声明新变量,如果有异常,只是赋值语句不会执行),并且在finally之前执行。返回的是新变量,所以结果是102;

    案例五

     1   class Person
     2     {
     3         public int Age { get; set; }
     4     }
     5    
     6     class Program
     7     {
     8         static void Main(string[] args)
     9         {
    10             Console.WriteLine(T1());
    11 
    12             Console.ReadKey();
    13         }
    14         static Person GetPerson()
    15         {
    16             Person p = new Person();
    17             p.Age = 100;
    18             try
    19             {
    20                 p.Age++;
    21                 //int x=1,y=0;
    22                 //Console.WriteLine(x/y);
    23                 return p;
    24             }
    25             catch (Exception)
    26             {
    27                 p.Age++;
    28                 return p;
    29             }
    30             finally
    31             {
    32                 p.Age++;
    33             }
    34         }
    View Code

    return p的时候,新变量=p;引用类型的值传递,相当于新变量和p同时指向原来的空间。try中的Age++后,赋值给新变量,然后执行finally中的Age++;最后return新变量,由于新变量和p指向同一块内存,所以Age最终改变了,输出102;

    如果抛出异常,同样的道理,输出的结果是103;

  • 相关阅读:
    【转】python 面向对象(进阶篇)
    【转】Python 面向对象(初级篇)
    【转】MySQL— pymysql and SQLAlchemy
    【转】MySQL— 索引
    pycharm+pygame飞机大战
    python+Django创建购物网站(二)
    python语言系统学习(三)
    复习NLP-实战(九)----语言模型
    Linux常用命令--跟K8S相关
    Nginx-ingress-controller部署应用
  • 原文地址:https://www.cnblogs.com/wesley168/p/6425991.html
Copyright © 2020-2023  润新知