C#结构化异常之自定义异常
首先先来了解下C#中所有的异常类型是如何来划分的。
在C#中所有的异常类型都继承自System.Exception,也就是说,System.Exception是所有异常类的基类. 总起来说,其派生类分为两种:
1. SystemException类: 所有的CLR提供的异常类型都是由SystemException派生。
2. ApplicationException类: 由用户程序引发,用于派生自定义的异常类型,一般不直接进行实例化。
下面看看是如何来定义异常类,以及自定义异常类如何来触发及捕获.
publicclass PayOverflowException:ApplicationException
{
///<summary>
/// 默认构造函数
///</summary>
public PayOverflowException() { }
public PayOverflowException(string message)
: base(message) { }
public PayOverflowException(string message, Exception inner)
: base(message, inner) { }
public PayOverflowException(System.Runtime.Serialization.SerializationInfo info,
System.Runtime.Serialization.StreamingContext context)
: base(info, context) { }
}
创建自定义异常类应严格遵循几个原则
1. 声明可序列化
2. 添加一个默认的构造函数
3. 添加包含message的构造函数
4. 添加一个包含message,及内部异常类型参数的构造函数
5. 添加一个序列化信息相关参数的构造函数.
以下介绍,如何来使用及触发自定义异常类型
还是以Empoyee类为例, 在GiveBonus()方法中加入一个判断语句,如果员工总的工资高于10000的话,就应该抛出异常, 由调用它的程序进行捕获。
为了便于在应用程序中明确的知道出现异常的详情,我采用的是抛出自定义异常类的对象的这种方式,这里用到的关键字throw. 这样在外层的程序进行异常
捕获的时候可以通过自定义异常类对象的Message属性得到详细的信息, 之后可以进行异常日志的记录、写入数据库等相关的处理。
1. Employee类及触发异常代码
{
publicint ID { get; set; }
publicstring Name { get; set; }
///<summary>
/// current pay
///</summary>
publicint CurrPay { get; set; }
public Employee() { }
public Employee(int id, string name, int currpay)
{
this.ID = id;
this.Name = name;
this.CurrPay = currpay;
}
///<summary>
/// 定义一个GiveBunus的虚方法以供不同的派生类进行重载
///</summary>
///<param name="amount">奖金额度</param>
publicvirtualvoid GiveBunus(int amount)
{
//用一个临时变量记录递增之前的值
var pay = CurrPay;
this.CurrPay += amount;
if (CurrPay >10000)
{
//发生异常,将CurrPay的值进行恢复,
//并抛出异常,外部程序捕获次异常
this.CurrPay = pay;
var ex =new PayOverflowException("The employee's max pay should be no more than 10000.");
throw ex;
}
}
}
2. 捕获自定义异常代码示例:
var emp =new Employee(10001, "Yilly", 8000);
try
{
emp.GiveBunus(3000);
}
catch (PayOverflowException ex)
{
Console.WriteLine("异常信息:{0}\n发生于{1}类的{2}方法", ex.Message,
ex.TargetSite.DeclaringType,ex.TargetSite.Name);
try
{
var file =new FileStream(@"c:\customerexception.txt", FileMode.Open);
//*** 异常信息写入文件中的代码省略...
}
catch (Exception ex1)
{
var inner =new PayOverflowException(ex.Message, ex1);
throw inner;
}
}
以上异常处理部分使用了try/catch的嵌套语句, 目的是为了防止在将异常信息写入日志文件操作的时候有可能会出现预料不到的异常而进行的异常捕获,那么最外层catch语句块中再次捕获异常的时候就会再次throw一个PayOverflowException的对象。
值得注意的是:在实例化的时候调用的是PayOverflowException(string message, Exception inner)构造函数,如果本程序如果有其他程序在调用的时候, 可以通过.InnerExcetpion的Message属性进行查看内部异常。
最后来看下程序运行的结果:
以上是我对C#自定义异常的一些理解,有不足之处请不吝赐教,也欢迎针对这一话题进行讨论。