异常处理
异常提供了一种把程序控制权从某个部分转移到另一个部分的方式。C#异常处理时建立在四个关键词之上的:try、catch、finally和throw。
try:一个try块标识了一个将被激活的特定的异常的代码块。后跟一个或多个catch块。
catch:程序通过异常处理程序捕获异常。catch关键字表示异常的捕获。
finally:finally 块用于执行给定的语句,不管异常是否被抛出都会执行。
throw:当问题出现时,程序抛出一个异常。使用throw关键字来完成。
捕获异常
捕获异常是通过try…catch语句实现的,语法格式如下:
try
{ // 引起异常的语句 }
catch( ExceptionName e1 )
{ // 错误处理代码 }
其中,try关键字标识了一个有异常的代码块。后跟可以一个或多个catch块。而catch关键字表示异常的捕获。
编写程序,利用try…catch语句捕获数组的越界问题。
using System;
namespace Project1
{
class Program
{
static void Main(string[] args)
{
int[] myint = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
try
{
for (int i = 0; i <= myint.Length; i++)
{
Console.Write(myint[i].ToString() + " ");
}
}
catch (Exception myex)
{
Console.WriteLine(myex.Message.ToString());
}
Console.ReadKey();
}
}
}
【程序分析】本例演示了捕获异常。在代码中,首先定义一个数组myint,并为其赋值;然后通过for循环进行遍历,需要注意的是,由于循环变量i应该小于数组myint中所有元素的总数,但是当书写为“i <=myint.Length;”时,就会造成数组的越界问题;接着,再将这段有异常的for循环语句放入到try语句中,并通过catch语句捕获异常,描述出造成异常的原因。
0 1 2 3 4 5 6 7 8 9 索引超出了数组界限。
清除、处理异常
如果用户对产生的异常不进行处理,只是通过catch语句进行捕获,则任然无法消除为错误所分配的资源。所以需要使用try…finally语句清除异常
![(https://img-blog.csdnimg.cn/08369748a6dc45eebe31004d1dfbbc85.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA6L-O6L-O5LiA56yR,size_17,color_FFFFFF,t_70,g_se,x_16)
编写程序,输出尝试除以零所引发的异常。
using System;
namespace Project2
{
class Program
{
static void Main(string[] args)
{
int[] myint = { 0, 2, 4, 6, 8, 10, 12, 14 };
for (int i = 0; i < myint.Length; i++)
{
int temp = 720 / myint[i];
Console.WriteLine("720÷{0}={1}", myint[i], temp);
}
Console.ReadKey();
}
}
}
【程序分析】在代码中,首先定义了一个数组myint,并为其赋值;接着通过for循环,输出720除以每个数组元素的值,但是由于数组中有个元素值为0,所以引发了一个异常,该异常的原因是“尝试除以零”。
“System.DivideByZeroException”类型的未经处理的异常在 Project2.exe 中发生
尝试除以零。
编写程序,利用try…catch…finall语句清除上例中的异常,确保程序正常运行。
using System;
namespace Project3
{
class Program
{
static void Main(string[] args)
{
int[] myint = { 0, 2, 4, 6, 8, 10, 12, 14 };
try
{
for (int i = 0; i < myint.Length; i++)
{
int temp = 720 / myint[i];
Console.WriteLine("720÷{0}={1}", myint[i], temp);
}
}
catch (Exception myex)
{
Console.WriteLine(myex.Message.ToString());
}
finally
{
Console.WriteLine("无论是否发生异常,都会执行程序");
}
Console.ReadKey();
}
}
}
运行结果
尝试除以零。
无论是否发生异常,都会执行程序
引发异常
有时在编写程序时,需要故意引发异常,以便捕获到异常的信息。而throw语句就是用于主动引发一个异常。
finally语句虽然可以消除try语句块中分配的任何资源,但是它不管异常是否被抛出,程序都会执行。因此,增加catch语句,就可以完美地合并两种错误处理技术,即捕获异常、消除并执行应用程序。
引发异常的语法格式:
throw new 异常类(异常信息);
异常类可以是系统预定义的类,也可以是用户自定义的类,而异常信息通常都表现为一个字符串。
编写程序,在Program类中定义一个整型的私有静态方法,该方法含有一个字符串类型的参数。然后通过该方法将一个不能转换成整数的字符串转换成整数,并引发异常。
using System;
namespace Project4
{
class Program
{
//用户自定义一个整型的静态私有成员函数ConvertStringToInt
private static int ConvertStringToInt(string mystr)
{
int outnum = 0;
//在格式转换时可能发生的异常
try
{
//将字符串转换为整型
outnum = Convert.ToInt32(mystr);
return outnum;
}//如果outnum发生了异常,那么就在catch中抛出异常
catch
{
throw new FormatException("格式转换不正确");
}
}
static void Main(string[] args)
{
//在Main方法中调用ConvertStringToInt方法
string mystr = "hao123";
//在调用方法值也会引发一个异常
try
{
int myint = ConvertStringToInt(mystr);
Console.WriteLine(myint);
}
catch (FormatException exf)
{
Console.WriteLine(exf.Message.ToString());
}
Console.ReadKey();
}
}
}
【程序分析】本例演示了将字符串类型的数据转换成为整型数据,如果无法转换就抛出一个异常。
在代码中,用户首先自定义一个整型的静态私有成员函数ConvertStringToInt,在该函数的括号里定义一个字符串类型的形参mystr,用于接收Main方法传递过来的数据。在ConvertStringToInt方法中,首先定义变量outnum,用于存储转换好的整型数据,因此需要使用try…catch语句捕获该变量的异常,然后在catch语句中,抛出异常的原因。
在Main方法中,对ConvertStringToInt方法进行调用,但在调用时也需要使用try…catch语句捕获该方法引发的异常,并描述出来。
格式转换不正确
C#中的异常类
在C#中的异常,就是为了处理错误情况而提供的一种机制。它为每种错误情况提供了定制的处理方式,并且把标识错误的代码和预处理错误的代码分离开来。C#中的异常类主要是直接或间接地派生于System.Exception类,其中,System.ApplicationException类则是第三方定义的异常类,如果用户要自定义异常类,那么就从该类派生。下表列出了一些常见预定义的异常类。
C#中的异常类主要是直接或间接地派生于System.Exception类,其中System.ApplicationException类则是第三方定义的异常类,如果用户要自定义异常类,那么就从该类派生。
- IndexOutofRangeException类的使用
IndexOutofRangeException类用于描述试图访问索引超出界限的数组或集合的元素时引发的异常。
编写程序,定义一个数组,在遍历该数组时,超出该数组索引值的界限。
using System;
namespace Project5
{
class Program
{
static void Main(string[] args)
{
int[] myint = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
for (int i = 0; i < 11; i++)
{
Console.Write(myint[i] + " ");
}
Console.WriteLine();
Console.ReadKey();
}
}
}
“System.IndexOutOfRangeException”类型的未经处理的异常在 Project5.exe 中发生
索引超出了数组界限。
0 1 2 3 4 5 6 7 8 9
编写程序,使用IndexOutofRangeException类,捕获上例中的异常。
using System;
namespace Project6
{
class Program
{
static void Main(string[] args)
{
int[] myint = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
try
{
for (int i = 0; i < 11; i++)
{
Console.Write(myint[i] + " ");
}
}
catch (IndexOutOfRangeException exIOR)
{
Console.WriteLine(exIOR.Message.ToString());
}
Console.ReadKey();
}
}
}
【程序分析】本例通过try…catch语句捕获了Index OutofRangeException类描述遍历数组越界所引发的异常。
0 1 2 3 4 5 6 7 8 9 索引超出了数组界限。
- NullReferenceException的使用
NullReferenceException类用于描述尝试取消引用空对象,引用时所引发的异常。
编写程序,引用一个空值。
using System;
namespace Project7
{
class Program
{
static void Main(string[] args)
{
string mystr = null;
try
{
Console.WriteLine(mystr.ToString());
}
catch (NullReferenceException exNR)
{
Console.WriteLine(exNR.Message.ToString());
}
Console.ReadKey();
}
}
}
【程序分析】在代码中,定义了一个string类型的变量str,并赋予null值。由于访问一个变量的空值是没有任何意义的,所以try…catch捕获了NullReferenceException类描述的一个异常。
未将对象引用设置到对象的实例。