c#中的捕获派生类异常

转载 2013年12月03日 15:39:44

在尝试捕获涉及基类和派生类的异常类型时要注意catch子句的排序方式,因为基类的catch子句也会匹配它的任何派生类。例如,由于所有异常的基类都是Exception,因此带有catch的Exception会捕获所有可能的异常。当然,根据前面的描述,使用不带异常类型的catch提供了一种捕获所有异常的清晰方式。然而在其他背景下,捕获派生类异常的问题非常重要,尤其是在创建自己的异常时。

如果要捕获基类类型的异常和派生类类型的异常,那么将派生类先放在catch序列中。之所以有必要这样做,是因为基类catch也会捕获所有派生类。幸运的是,这个规则是自实施的,因为先放置基类会导致编译时错误。

下面的程序创建了分别名为ExceptA和ExceptB的两个异常类。ExceptA派生自Exception,ExceptB派生自ExceptA。然后程序抛出各个类型的异常。为了简单起见,仅提供了一个构造函数(接受一个描述异常的字符串作为实参)。但是要记住,在商业代码中,自定义的异常类一般会提供Exception定义的所有4个构造函数。

  1. // Derived exceptions must appear before base class exceptions.  
  2. using System;  
  3.  
  4. // Create an exception.  
  5. class ExceptA : Exception {  
  6.   public ExceptA(string str) : base(str) { }  
  7.  
  8.   public override string ToString() {  
  9.     return Message;  
  10.   }  
  11. }  
  12.  
  13. // Create an exception derived from ExceptA  
  14. class ExceptB : ExceptA {  
  15.   public ExceptB(string str) : base(str) { }  
  16.  
  17.   public override string ToString() {  
  18.     return Message;   
  19.   }  
  20. }  
  21.  
  22. class OrderMatters {  
  23.   static void Main() {  
  24.     for(int x = 0; x < 3; x++) {  
  25.       try {  
  26.         if(x==0) throw new ExceptA("Caught an ExceptA exception");  
  27.         else if(x==1) throw new ExceptB("Caught an ExceptB exception");  
  28.         else throw new Exception();  
  29.       }  
  30.       catch (ExceptB exc) {  
  31.         Console.WriteLine(exc);  
  32.       }  
  33.       catch (ExceptA exc) {  
  34.         Console.WriteLine(exc);  
  35.       }  
  36.       catch (Exception exc) {  
  37.         Console.WriteLine(exc);  
  38.       }  
  39.     }  
  40.   }  

该程序的输出如下所示:

  1. Caught an ExceptA exception  
  2. Caught an ExceptB exception  
  3. System.Exception: Exception of type 'System.Exception' was thrown.  
  4.    at OrderMatters.Main() 

注意catch子句的顺序,这是这些子句能够运行的唯一顺序。由于ExceptB是从ExceptA派生的,因此ExceptB的catch必须在ExceptA的catch之前。类似地,Exception(它是所有异常的基类)的catch必须最后出现。要亲自证实这一点,可以重新排列catch子句。这样做会导致编译时错误。

问:既然异常通常表示特定的错误,那么为什么要捕获基类异常呢?

答:捕获基类异常的catch子句可以捕获整个类别的所有异常,可以使用一个catch处理它们,从而可以避免重复的代码。例如,可以创建一组描述某种设备错误的异常。如果异常处理程序只是告诉用户发生了一种设备错误,那么可以对这种类型的所有异常使用一个共同的catch。处理程序可以简单地显示Message字符串。由于完成该操作的代码对于所有异常都是相同的,因此只使用一个catch就可以响应所有设备异常。

在本项目中,将创建可以由第9章的"试一试"一节中开发的队列类使用的两个异常类。这两个异常类将指出队列满与队列空时错误发生的条件。当发生错误时,分别由Put()和Get()方法抛出异常。为了简洁起见,本示例仅向SimpleQueue类中添加这些异常,但是可以方便地将它们合并到其他队列类中。为了简短起见,异常类仅实现程序中实际使用的构造函数(它是接受一个描述异常的实参的构造函数)。您可以尝试亲自添加其他构造函数。

操作步骤

(1) 创建名为QExcDemo.cs的文件。

(2) 在QExcDemo.cs中,定义如下异常:

  1. // Add exception handling to the queue classes.  
  2.  
  3. using System;  
  4.  
  5. // An exception for queue-full errors.  
  6. class QueueFullException : Exception {  
  7.   public QueueFullException(string str) : base(str) { }  
  8.   // Add other QueueFullException constructors here, if desired.  
  9.  
  10.   public override string ToString() {  
  11.     return "\n" + Message;  
  12.   }  
  13. }  
  14.  
  15. // An exception for queue-empty errors.  
  16. class QueueEmptyException : Exception {  
  17.   public QueueEmptyException(string str) : base(str) { }  
  18.   // Add other QueueEmptyException constructors here, if desired.  
  19.  
  20.   public override string ToString() {  
  21.     return "\n" + Message;  
  22.   }  
  23. 当试图将元素存储到已满的队列中时,生成QueueFullException异常。当试图从空队列中删除元素时,生成QueueEmptyException异常。

    (3) 按如下代码所示修改SimpleQueue类,使它在发生错误时抛出异常。将修改后的类添加到QExcDemo.cs中。

    1. // A simple, fixed-size queue class for 
      characters that uses exceptions.
       
    2. class SimpleQueue : ICharQ {      
    3.   char[] q; // this array holds the queue      
    4.   int putloc, getloc; // the put and get indices      
    5.       
    6.   // Construct an empty queue given its size.     
    7.   public SimpleQueue(int size) {   
    8.     q = new char[size+1]; // allocate memory for queue      
    9.     putloc = getloc = 0;      
    10.   }      
    11.      
    12.   // Put a character into the queue.      
    13.   public void Put(char ch) {  
    14.     if(putloc==q.Length-1)   
    15.       throw new QueueFullException("Queue Full! Max length is " +  
    16.                                     (q.Length-1) + ".");  
    17.           
    18.     putloc++;      
    19.     q[putloc] = ch;      
    20.   }      
    21.       
    22.   // Get a character from the queue.     
    23.   public char Get() {  
    24.     if(getloc == putloc)   
    25.       throw new QueueEmptyException("Queue is empty.");  
    26.         
    27.     getloc++;      
    28.     return q[getloc];      
    29.   }      

    向SimpleQueue类中添加异常可以以合理的方式处理队列错误。SimpleQueue类以前的版本只是简单地报告错误。抛出异常的方式要好很多,因为它允许使用SimpleQueue类的代码以适当的方式处理错误。

    (4) 为了尝试使用更新后的SimpleQueue类,将如下所示的QExcDemo类添加到QExcDemo.cs中。

    1. // Demonstrate the queue exceptions.  
    2.  
    3. class QExcDemo {      
    4.   static void Main() {      
    5.     SimpleQueue q = new SimpleQueue(10);      
    6.     char ch;      
    7.     int i;      
    8.       
    9.     try {   
    10.       // Overrun the queue.  
    11.       for(i=0; i < 11; i++) {  
    12.         Console.Write("Attempting to store : " +  
    13.                          (char) ('A' + i));  
    14.         q.Put((char) ('A' + i));      
    15.         Console.WriteLine(" -- OK");  
    16.       }  
    17.       Console.WriteLine();  
    18.     }  
    19.     catch (QueueFullException exc) {  
    20.       Console.WriteLine(exc);  
    21.     }  
    22.     Console.WriteLine();  
    23.      
    24.     try {  
    25.       // Over-empty the queue.  
    26.       for(i=0; i < 11; i++) {       
    27.         Console.Write("Getting next char: ");  
    28.         ch = q.Get();      
    29.         Console.WriteLine(ch);      
    30.       }  
    31.     }  
    32.     catch (QueueEmptyException exc) {  
    33.       Console.WriteLine(exc);  
    34.     }   
    35.   }      

    (5) 为了创建程序,必须使用IQCar.cs文件编译QExcDemo.cs。IQChar.cs中包含了队列接口。当运行QExcDemo时,将看到如下输出:

    1. Attempting to store : A -- OK  
    2. Attempting to store : B -- OK  
    3. Attempting to store : C -- OK  
    4. Attempting to store : D -- OK  
    5. Attempting to store : E -- OK  
    6. Attempting to store : F -- OK  
    7. Attempting to store : G -- OK  
    8. Attempting to store : H -- OK  
    9. Attempting to store : I -- OK  
    10. Attempting to store : J -- OK  
    11. Attempting to store : K  
    12. Queue Full! Max length is 10.  
    13.  
    14. Getting next char: A  
    15. Getting next char: B  
    16. Getting next char: C  
    17. Getting next char: D  
    18. Getting next char: E  
    19. Getting next char: F  
    20. Getting next char: G  
    21. Getting next char: H  
    22. Getting next char: I  
    23. Getting next char: J  
    24. Getting next char:   
    25. Queue is empty. 

如何判断所捕获的异常类型,并根据其进行优雅处理

/* C# typeof() 和 GetType()区是什么? 1、typeof(x)中的x,必须是具体的类名、类型名称等,不可以是变量名称。 2、GetType()方法继承自Object,所以C...
  • u010178308
  • u010178308
  • 2017年09月17日 23:53
  • 188

C#中的异常捕获机制(try catch finally)

C#中的异常捕获机制(try catch finally) 标签: c#exception数学计算classsystemc 2011-10-24 18:45 30213人阅读 评论(4) ...
  • kasama1953
  • kasama1953
  • 2016年08月12日 00:19
  • 13859

异常捕获和file类

1.异常捕获 1)异常是什么:异常是在程序的编写过程中出现的一些异于常态的事情,比如说a除以b,当b被赋值为0时,则程序就会抛出异常 2)异常的处理方法:通过try..catch的方法来捕获异常或者通...
  • a452228300
  • a452228300
  • 2017年03月29日 21:22
  • 287

Release异常捕获

  • 2008年10月21日 17:50
  • 7KB
  • 下载

C#中的异常捕获机制(try catch finally)

C#中的异常捕获机制(try catch finally) 标签: c#exception数学计算classsystemc 2011-10-24 18:45 30213人阅读 评论(4) ...
  • kasama1953
  • kasama1953
  • 2016年08月12日 00:19
  • 13859

黑马程序员_C#中数据类型的转换和异常捕获机制

------- Windows Phone 7手机开发、.Net培训、期待与您交流! ------- 数据类型的转换: (1)自动转换 当参与运算的操作数和结果的类型不一致时,满足以下两个条件,系统将...
  • histrainbow
  • histrainbow
  • 2014年07月16日 13:10
  • 640

Java Exception 捕获和展示

在进行Java B/S架构开发时,经常有这样的场景:后端处理业务逻辑,前端负责展示,当后端处理出现异常时,如何把错误信息展示给前台呢?错误信息栈通常很多,对开发人员查找问题比较方便,但对于客户来说,打...
  • hongweigg
  • hongweigg
  • 2014年01月15日 16:43
  • 38852

捕获异常

private void CatchError() { try { checked // 某些不是错误的异常可用该方法捕获 ...
  • LIQIANGEASTSUN
  • LIQIANGEASTSUN
  • 2014年12月23日 15:08
  • 646

C#中的异常捕获机制(try catch finally)

转载自:http://blog.csdn.net/zevin/article/details/6901489 一、C#的异常处理所用到关键字 try 用于检查发生的异常,并帮助发送任何可能的异...
  • u013028876
  • u013028876
  • 2016年01月16日 16:55
  • 1870

C# WinForm捕获全局异常(捕获未处理的异常)

原文地址:http://www.cnblogs.com/wangshenhe/archive/2012/11/14/2769605.html 许多小公司的项目都缺少异常处理模块,我们也是。经...
  • mar_ljh
  • mar_ljh
  • 2015年05月05日 17:27
  • 4780
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:c#中的捕获派生类异常
举报原因:
原因补充:

(最多只允许输入30个字)