自定义异常类

    FCL定义的系统异常不能解决所有问题,在实际项目中,我们通常要根据自己的需要定义自己的异常类,以便于我们能够更好地捕获异常信息。接下来我将自己定义的异常类一步步贴上来,供彼此交流,学习,不当之处还望指正。

(1)定义异常类MyException,该类继承于Exception,实现了ISerializable接口。代码如下:

View Code
1 //Serializable指定了自定义异常类可以被序列化
2   [Serializable]
3 public class MyException : Exception, ISerializable
4 {
5 //自定义本地文本信息
6   private string myMsg;
7
8 public string MyMsg
9 {
10 get
11 {
12 return myMsg;
13 }
14 }
15 //重写只读本地文本信息属性
16 public override string Message
17 {
18 get
19 {
20 string msgBase = base.Message;
21 return myMsg == null ? msgBase : msgBase + myMsg;
22 }
23 }
24 //实现基类的各公有构造函数
25 public MyException()
26 : base()
27 {
28 }
29 public MyException(string message)
30 : base(message)
31 {
32 }
33 public MyException(string message, Exception innerException)
34 : base(message, innerException)
35 {
36 }
37
38 //为新增字段实现构造函数
39 public MyException(string message, string myMsg)
40 : this(message)
41 {
42 }
43 public MyException(string message, string myMsg, Exception innerException)
44 : this(message, innerException)
45 {
46 this.myMsg = myMsg;
47 }
48 //用于序列化的构造函数,以支持跨应用程序域或远程边界的封送处理
49 public MyException(SerializationInfo info, StreamingContext context)
50 : base(info, context)
51 {
52 }
53 //重写基类GetObjectData()方法,实现向SerializationInfo中添加自定义字段信息
54 public override void GetObjectData(SerializationInfo info, StreamingContext context)
55 {
56 info.AddValue("MyMsg", myMsg);
57 base.GetObjectData(info, context);
58 }
59 }

(2)声明一个额外的类,用于测试自定义的异常类,代码如下

1 class TestMyException
2 {
3 //函数只接受1到100的数字,如若不在此范围,则抛出自定义的异常
4   public void Set(int i)
5 {
6 //若输入的数字大于100
7   if (i > 100)
8 {
9 //初始化一个自定义异常类MyException
10 MyException e = new MyException("这是自定义异常类抛出的信息:输入的数字超过100了,请小点!", "这是系统抛出的异常信息");
11 // e 首先进行了Data和HelpLink属性的初始化,这两个属性都是继承于Exception
12 e.Data.Add("MY", "自定义的异常");
13 e.Data.Add("Time", DateTime.Now);
14 e.HelpLink = "http://www.baidu.com";
15 throw e;
16 }
17 else if (i < 1)
18 {
19 MyException e = new MyException("这是自定义异常类抛出的信息:输入的数字不足1,请大点!", "这一部分是系统抛出的异常信息");
20 e.Data.Add("MY", "自定义的异常");
21 e.Data.Add("Time", DateTime.Now);
22 e.HelpLink = "http://www.baidu.com";
23 throw e;
24 }
25 //输入的数字在1-100之间
26 Console.WriteLine("输入的数字“{0}”在范围(1~100)内。",i);
27 }
28 }

(3)客户端代码:

View Code
1 class Program
2 {
3 static void Main(string[] args)
4 {
5 Console.WriteLine("Please input a numeral!");
6 try
7 {
8 //接收输入的数字并转化为int型,若输入为字符,会抛出系统自带的异常"Input string was not in current format"
9 int input = Convert.ToInt32(Console.ReadLine());
10 TestMyException tst = new TestMyException();
11 tst.Set(input);
12 Console.WriteLine("通过测试,没抛出异常");
13 }
14 //多个catch块在一起的时候,编译器uaoqiu将特定程度较高的异常放在最前边,而程度不高的异常类放在后边
15 //也就是说在异常类的继承机构中,把最底层的类例如System.Exception放在最后一个catch块中,而教高层的类放在最前边。
16 //刚好跟异常类的”树形“成倒状
17 catch (MyException ex)
18 {
19 Console.WriteLine("输入的数字不在1到100以内,故抛出自定义异常");
20 Console.WriteLine("异常信息:{0}", ex.Message);
21 Console.WriteLine("发生时间:{0}", ex.Data["Time"]);
22 Console.WriteLine("更多帮助:{0}", ex.HelpLink);
23 }
24 catch (Exception ex)
25 {
26 Console.WriteLine("系统异常信息:{0}", ex.Message);
27 }
28 Console.ReadLine();
29 }
30 }
运行结果为:
(1)若输入的数字在1-100之间,则不让其抛出异常,运行效果如图(1)
1
(2)若输入的数字大于100,抛出异常,过大,运行效果如图(2)
2
(3)若输入的数字小于1,抛出异常,过小,运行效果如图(3)
3
 
最后小结一下自定义异常类需要注意的地方:

1 选择合适的基类继承,一般情况下我们选择Exception或者其派生类作为自定义异常类的基类。

2 System.Exception提供了三个构造函数,一般情况下,在自定义的异常类中也应该实现这三个构造函数,并且最好调用其基类中相应的构造函数,如果自定义类中还有新的字段要处理,则应该为新的字段实现新的构造函数来实现

3 所有的异常类型都是可序列化的,因此必须为自定义异常类添加SerializableAttribute特性,并实现ISerializable接口

4 以Exception作为自定义异常类的类名的后缀,良好的编程习惯

5 在自定义异常类中包括本地化描述信息,也就说实现异常类的Message属性,而不是从基类继承Message。

 
posted @ 2011-06-02 16:49  liujb  阅读(769)  评论(0编辑  收藏  举报