结构化异常处理
学习目标:
了解异常处理的基本知识
掌握如何抛出和捕获异常
理解嵌套try语句使用
了解掌握异常类
理解finally块
异常处理的基本知识
结构化异常处理测试特定的代码段,并在发生异常处理时改变错误情况或意外行为。
抛出和捕获异常
抛出和捕获异常是由try/catch/finally语句处理的,是异常处理的主要机制。
在C#处理异常时,需要在代码块中关注两个部分:一是可能导致异常的代码段(通常称为抛出异常),二是当执行过程中发生异常时将要执行的代码段(通常称为捕获异常)。
try/catch/finally语句块的基本语法如下:
try
{
//可能产生异常的代码块
}
catch (Exception e)
{
//对异常进行处理的代码段
}
finally
{
//最终执行的代码块(无论是否产生异常,都会执行)
}
如果没有错误发生,程序就会正常执行。如果发生异常,公共语言库将找到此代码最近一层的try块,而不用运行任何附加代码块。然控制传递到匹配的catch块2(如果有),并传递到关联的finally块。
如果发生异常,代码就会执行一定的操作,称为“抛出一个异常”。抛出一个异常就是实例化对象,并将其抛出,如下所示:
throw new Exception();
上面的语句实例化了Exception类的一个异常对象,在try中遇到throw语句,就会查找与这个try块对应的catch块。如果有多个对应的catch块,那么就会检查与catch块对应的异常类,确定正确的catch块。当抛出一个Exception对象时,程序会跳转到下面的catch块上:
catch(Exception e)
{
//处理异常代码
}
下面举例说明如何抛出和捕获一个异常。在示例中,定义3个整形变量,当使用0作为除数时,将会发生异常,代码如下:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 class Program
2 {
3 static void Main(string[] args)
4 {
5 int a = 0;
6 int b = 10;
7 int c = 0;
8 try
9 {
10 a = b / c;
11 }
12 catch (Exception e)
13 {
14 Console.WriteLine("发生异常:{0}", e.Message);
15 }
16 finally
17 {
18 Console.ReadLine();
19 }
20 }
21 }
在上述代码中,当除数为0时抛出异常,语句块catch(Exception e)将成捕获该异常。
运行结果如下:
try-catch错误处理表达式允许将任何可能发生异常情形的程序代码放在try块进行监控,真正处理错误异常的程序代码则被放置在catch块中,一个try块可对应多个catch块,举例说明如何使用多个catch快捕捉多个异常,代码如下:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 class myclass
2 {
3 static void ProcessString(string str)
4 {
5 if (str == null)
6 {
7 throw new ArgumentNullException();
8 }
9 }
10 static void Main(string[] args)
11 {
12 Console.WriteLine("输出结果为:");
13 try
14 {
15 string str = null;
16 ProcessString(str);
17 }
18 catch (ArgumentNullException e)
19 {
20 Console.WriteLine("第一个异常:{0}", e.Message);
21 }
22 catch (Exception e)
23 {
24 Console.WriteLine("第二个异常:{0}", e.Message);
25 }
26 finally
27 {
28 Console.ReadLine();
29 }
30 }
本例中通过catch语句块进行捕获异常,分别是ArgumentNullException异常和Exception异常。
运行结果为:
注意:如果没有catch语句块,程序会异常终止,使用不带参数的catch子句4,则可以捕获任何异常类型。
嵌套try语句:try语句允许嵌套,语句如下:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 try
2 {
3 //代码块1
4 try
5 {
6 //代码块2
7 }
8 catch
9 {
10 //代码块3
11 }
12 finally
13 {
14 // 最终代码
15 }
16 //代码块4
17 }
18 catch
19 {
20 //异常处理
21 }
22 finally
23 {
24 // 最终代码
25 }
如果异常在外层的try块中抛出,异常由外层的catch块捕获,并执行外层的finally块。如果异常在内层的try块(代码块2)中抛出,且有一个合适的内层catch块处理该异常,执行内层的finally块之后,继续执行外层的try块(标记为4代码块)。
主要的异常类
System.Exception类是其他异类的基类。System.Exception表示应用程序执行期间发生的错误。大多数异常对象都是Exception的某个派生类的实例。不过,任何从Object类派生的对象都可以作为异常引发。
Exception 类成员的使用:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 class exception
2 {
3 static void Main(string[] args)
4 {
5 try
6 {
7 Exception myEx = new Exception("原始异常");
8 throw myEx;
9 }
10 catch (Exception ex)
11 {
12 Console.WriteLine("异常类型:{0}", ex.GetType().ToString());//GetType方法获取当前实例的运行时类型,ToString方法用于创建并返回当前异常的字符串表示形式
13 Console.WriteLine("异常信息:{0}", ex.Message);//Message获取描述当前异常的消息
14 Console.WriteLine("堆栈跟踪:{0}", ex.StackTrace);//StackTrace用于获取当前异常发生时调用堆栈上方法的信息,有助于跟踪抛出异常的方法
15 Console.WriteLine("应用程序名称:{0}", ex.Source);//Source用于获取或设置导致错误的应用程序或对象的名称
16 }
17 finally
18 {
19 Console.ReadLine();
20 }
21 }
22 }
运行程序,结果输出如下:
抛出预定义异常:也就是抛出内部异常类的对象
自定义异常:自定义的异常在异类中扮演一个非常重要的角色,建立一个自定义异常类,继承于ApplictionException类,
//自定义异常类
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 class numException : ApplicationException
2 {
3 public void printError()
4 {
5 Console.WriteLine("输入的数小于1或者大于9,请重新输入!!");
6 }
7 }
8 class CustomException
9 {
10 static void Main(string[] args)
11 {
12 string num;
13 do
14 {
15 Console.WriteLine("请输入一个数,输入'exit'退出程序!");
16 num=Console.ReadLine();
17 System.Text.RegularExpressions.Regex rx=new System.Text.RegularExpressions.Regex (@"^[1-
18 9]$");//使用正则表达式判断
19 try
20 {
21 if (rx.IsMatch(num))
22 {
23 for(int i=0;i<10;i++)
24 {
25 Console.WriteLine("{0}*{1}={2}",i,num,i*Convert.ToInt32(num));
26 }
27 }
28 else
29 {
30 //抛出异常错误
31 throw new numException ();
32 }
33 //捕获异常
34 }
35 catch (numException ex)
36 {
37 ex.printError();
38 Console.WriteLine("异常类型:{0}"ex.GetType().ToString());
39 }
40 }while (!num.ToLower().Equals("exit"));
41 }
42 }
输出结果:
finally块
发生异常时,执行将终止,并且交给最近的异常处理程序。Finally块可以确保发生异常时执行所有的清理工作
finally块工作方式:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 class myFinally
2 {
3 static void Main(string[] args)
4 {
5 int[] array1 ={ 0, 0 };
6 int[] array2 ={ 0, 0 };
7 try
8 {
9 Array.Copy(array1, array2,-1);
10 }
11 catch (ArgumentOutOfRangeException e)
12 {
13 Console.WriteLine("Error:{0}",e);
14 }
15 finally
16 {
17 Console.WriteLine("总是执行finally块");
18 }
19 Console.ReadLine();
20 }
21 }
运行程序,不管是否发生异常,finally块都会执行,结果如下:
注意:finally块必须和try/catch快一起使用,不管是否发生异常,finally块都将保证运行