一、错误、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 else 24 { 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 else 35 { 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代码块就直接略过,说明一切正常。
结构化异常处理(一)