一、构建一个强类型异常来表示当前问题的独特细节效果会更好。
假定要构建一个名为CarIsDeadException的自定义异常来表示加速注定要损坏的汽车的错误。
1.创建一个派生自System.Exception/System.ApplicationException的新类(按照约定,所有的一场类均应以“Exception”后缀结束,这是.NET的最佳实践)。
1 namespace CustomException 2 { 3 public class CarIsDeadException : ApplicationException 4 { 5 private string messageDetails = String.Empty; 6 public DateTime ErrorTimeStamp { get; set; } 7 public string CauseOfError { get; set; } 8 9 public CarIsDeadException() { } 10 11 public CarIsDeadException(string message, string cause, DateTime time) 12 { 13 messageDetails = message; 14 CauseOfError = cause; 15 ErrorTimeStamp = time; 16 } 17 18 //重写Exception.Message属性 19 public override string Message 20 { 21 get 22 { 23 return string.Format("Car Error Message: {0}", messageDetails); 24 } 25 } 26 } 27 }
2.引发异常
从Accelerate()引发异常很直接,只需分配、配置和引发一个CarIsException类型,而不是通过System.Exception异常。
1 public void Accelerate(int delta) 2 { 3 ...... 4 5 CarIsDeadException ex = new CarIsDeadException(string.Format("{0} has overheated!", PetName), "You have a lead foot", DateTime.Now); 6 ex.HelpLink = "http://www.CarsRus.com"; 7 throw ex; 8 ...... 9 }
3.捕获异常
1 namespace CustomException 2 { 3 class Program 4 { 5 static void Main(string[] args) 6 { 7 Car myCar = new Car("Rusty", 90); 8 9 try 10 { 11 myCar.Accelerate(50); 12 } 13 catch (CarIsDeadException e) 14 { 15 Console.WriteLine(e.Message); 16 Console.WriteLine(e.ErrorTimeStamp); 17 Console.WriteLine(e.CauseOfError); 18 } 19 } 20 } 21 }
通常情况下,仅需在出现错误的类与该错误关系紧密时才需要创建自定义异常(例如,一个自定义文件类引发许多文件相关的错误,一个Car类引发许多汽车相关的错误,一个数据访问对象引发关于特定数据库表的错误)。这样我们就能使调用者逐个地处理众多的异常。
二、改进
为了配置自定义错误信息,当前的CarIsDeadException类重写了System.Exception.Message属性,并提供两个自定义属性来说明其他数据。
事实上,不要重写Message虚属性,而只需要将传入的信息按以下方式传递给父对象的构造函数:
1 namespace CustomException 2 { 3 public class CarIsDeadException : ApplicationException 4 { 5 public DateTime ErrorTimeStamp { get; set; } 6 public string CauseOfError { get; set; } 7 8 public CarIsDeadException() { } 9 10 //将信息传递给父类对象构造函数 11 public CarIsDeadException(string message, string cause, DateTime time) 12 :base(message) 13 { 14 CauseOfError = cause; 15 ErrorTimeStamp = time; 16 } 17 } 18 }
很多情况下,自定义异常类的作用并不是提供继承基类之外附加的功能,而是提供明确标识错误种类的强命名类型,因此客户会为不同类型的异常提供不同的处理程序了逻辑。
三、构建一个严谨规范的自定义异常类
1.继承自Exception/ApplicationException类;
2.有[System.Serializable]特殊标记;
3.定义一个默认的构造函数;
4.定义一个设定继承的Message属性的构造函数;
5.定义一个处理“内部异常”的构造函数;
6.定义一个处理类型序列化的构造函数。
例:
1 [Serializable] 2 public class CarIsDeadException : ApplicationException 3 { 4 public CarIsDeadException() { } 5 public CarIsDeadException(string message) 6 :base(message) 7 { 8 9 } 10 public CarIsDeadException(string message, System.Exception inner) 11 :base(message ,inner) 12 { 13 14 } 15 protected CarIsDeadException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) 16 :base(info, context) 17 { 18 19 } 20 ...... 21 }
Visual Studio提供了一个叫做“Exception”的代码段模板,它能自动生成一个新的遵循.NET最佳实践的异常类。输入“exc”并连按两次Tab键来激活代码。
结构化异常处理(四)构建自定义异常