异常处理

一、为什么需要处理异常

二、异常的种类

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;

 

posted @ 2017-02-21 20:13  wesley1680  阅读(146)  评论(0编辑  收藏  举报