首页 > 代码库 > 结构化异常处理(一)

结构化异常处理(一)

一、错误、bug与异常

在.NET术语命名中,“异常”解释为bug、用户输入错误和运行时错误。

二、.NET异常处理的作用

理想情况下,我们希望将这个错误的名称、消息和其他的有用信息都打进一个明确的包内,这正是结构化异常处理所做的。

结构化异常处理方案的优点:

1.开发人员现在又了统一的而且对.NET领域内各种语言都通用的方式来处理错误。

2.用以引发核捕获异常的语法在不同程序集间或计算机间都是一致的。

3.我们不再是通过接收意义模糊的数字常量来确定问题,而是可以通过异常,它包含容易度读懂的问题描述和首次触发异常时调用栈的详细快照。此外,我们还能够为最终用户提供响应的帮助链接,将他们引向一个URL,其中包含相应错误的详细信息和程序员自定义的数据。

三、.NET异常处理的四要素

结构化异常处理编程要使用4个互相关联的实体:

1.一个表示异常详细信息的类类型;

2.一个向调用者抛出异常类实例的成员;

3.调用者的一段调用异常代码的代码块;

4.调用者的一段(处理)捕获将要发生异常的代码块。

C#编程语言提供4个允许我们引发和处理异常的关键字:try、catch、throw和finally。用来表示问题的类型是一个继承自System.Exception的类。

四、System.Exception基类

System.Exception类型的核心成员

System.Exception属性                                                                                  作用
Data  IDictionary类型只读此属性返回一个键/值对集合(表示一个实现IDictionary接口的对象),提供有关异常的更多程序员定义信息。该集合默认情况为空。
HelpLink string类型此属性返回一个URL,指向包含详细错误信息描述的帮助文件或网站
InnerException  Exception类型 只读此属性为只读的,可用来获取导致当前异常发生的上一个异常的相关信息。上一个异常作为参数被传入当前异常的构造函数而被记录下来。
Message string类型只读,通过构造函数赋值此属性为只读的,它返回指定错误的文字描述。错误信息本身就是构造函数的一个参数。
Source string类型 只读次属性返回引发异常的程序集或对象的名称。
StackTrace string类型 只读此属性为只读的,它包含一个标识触发异常调用序列的字符串。在调试过程中,或者要将错误转储到外部错误的日志中时,这个属性非常有用。
TargetSite MethodBase类型 只读此属性为只读的,他返回一个MethodBase对象,其中描述了引发异常的方法的许多细节。

 

 

 

 

 

 

五、一个简单的例子

定义一个Car类,如果用户加速一个Car对象超过预先定义的最大速度,Car的引擎就会爆炸,使Car不能再用。

如果用户在车坏了之后还试图加速汽车,就会引发异常。这里将创建并设定一个新的System.Exception类的实例,并通过类的构造函数为只读属性Message赋值。如果将异常对象返回给被调用者,可以使用C#的throw关键字。

 1.引发普通的异常

 1 public class Car 2     { 3         public Car() { } 4         public Car(string name, int speed) 5         { 6             CurrentSpeed = speed; 7             PetName = name; 8         } 9         //表示最大速度10         private const int MaxSpeed = 100;11         //Car是否仍可操纵12         private bool casIsDead;13 14         public int CurrentSpeed { get; set; }15         public string PetName { get; set; }16 17         public void Accelerate(int delta)18         {19             if (casIsDead)20             {21                 Console.WriteLine("{0} is out of order...", PetName);22             }23             else24             {25                 CurrentSpeed += delta;26                 if (CurrentSpeed >= MaxSpeed)27                 {28                     casIsDead = true;29                     CurrentSpeed = 0;30 31                     //使用throw关键字引发异常32                     throw new Exception(string.Format("{0} has overheated!", PetName));33                 }34                 else35                 {36                     Console.WriteLine("=> CurrentSpeed = {0}", CurrentSpeed);37                 }38             }39         }40     }

2.捕获异常

 1 static void Main(string[] args) 2 { 3         Car myCar = new Car("Zippy", 20); 4  5         try 6         { 7               for (int i = 0; i < 10; i++) 8               { 9                     myCar.Accelerate(10);10               }11          }12          catch (Exception e)13          {14                 Console.WriteLine("Method: {0}", e.TargetSite);15                 Console.WriteLine("Message: {0}", e.Message);16                 Console.WriteLine("Source: {0}", e.Source);17          }18 }

结果:
=> CurrentSpeed = 30
=> CurrentSpeed = 40
=> CurrentSpeed = 50
=> CurrentSpeed = 60
=> CurrentSpeed = 70
=> CurrentSpeed = 80
=> CurrentSpeed = 90
Method: Void Accelerate(Int32)
Message: Zippy has overheated!
Source: ConsoleApplication3

说明:

1.当调用一个可能引发异常的方法时,应该使用try/catch块。一旦捕获到异常对象,将能够调用异常对象成员来释放问题的详细信息。

2.try块时执行过程中可能引发异常的语句的一部分。如果检测到一个异常,程序执行流进如响应的catch块。另一方面,如果try快内包含的代码没有触发异常,响应的catch代码块就直接略过,说明一切正常。