代码改变世界

异常设计准则

2011-08-30 22:13  Dirichlet  阅读(569)  评论(0编辑  收藏  举报

1. 抛出异常/设计异常(框架层)

a. 先捕获,包装捕获的异常再抛出。包装异常时务必要指定内部异常。

 1         public void SendMessages()
 2         {
 3             try
 4             {
 5                 EstablishConnection();
 6             }
 7             catch (System.Net.Sockets.SocketException e)
 8             {
 9                 throw new CommunicationFailureException("Cannot access remote computer.", e);
10             }
11         }

 

b. 异常消息进行本地化,支持多语言。
//设计当前引发异常层次(当前框架层次)的所有错误代码,每个异常都有一个错误代码表示。

 1     // Create the derived exception class.
 2     class SecondLevelException : Exception
 3     {
 4         const int SecondLevelHResult = unchecked((int)0x81234567);
 5 
 6         // Set HResult for this exception, and include it in the exception message.
 7         public SecondLevelException(string message, Exception inner) :
 8         base(string.Format("(HRESULT:0x{1:X8}) {0}", message, SecondLevelHResult), inner)
 9         {
10             HResult = SecondLevelHResult;
11         }
12 
13         public SecondLevelException(string message) : base(message) { }
14 
15         public SecondLevelException() { }
16     }

 


2. 捕捉异常

a. 不要通过在框架代码中捕捉非特定异常(如 System.Exception、System.SystemException 等)来处理错误。除非1. 捕捉异常是为了继续传输异常,2. 或者当前的普通异常 

被视为一个警告,不应该阻碍程序的执行,3.如果了解特定异常在给定上下文中引发的条件。 否则的话不要去捕捉普通异常。

b. 捕捉底层的特定的(具体的)异常, 目的有两个,一个是能处理这个异常,一个是包装捕获的异常然后抛出有意义的消息给上层。

c.不要过多使用 catch。通常应允许异常在调用堆栈中往上传播。


3. 其他的一些小技巧:

a. 频繁引发异常会带来性能问题。如果一个实际的调用会频繁引发异常,可以考虑使用 Tester-Doer 模式来避免与异常相关的性能问题。也就是调用之前判断参数是否正常,来减少异常的引发。

 1 public class Doer
 2 {
 3     // Method that can potential throw exceptions often.
 4     public static void ProcessMessage(string message)
 5     {
 6         if (message == null)
 7         {
 8             throw new ArgumentNullException("message");
 9         }
10     }
11     // Other methods...
12 }
13 
14 public class Tester
15 {
16     public static void TesterDoer(ICollection<string> messages)
17     {
18         foreach (string message in messages)
19         {
20             // Test to ensure that the call
21             // won't cause the exception.
22             if (message != null)
23             {
24                 Doer.ProcessMessage(message);
25             }
26         }
27     }
28 }

 

b.对于可能在常见方案中引发异常的成员,可以考虑使用 TryParse 模式来避免与异常相关的性能问题。举例int.Parse, 提供两个方法int.TryParse和int.Parse,TryParse模式不引发异常,只返回一个布尔值。

 

c. 应用层最好加一个全局catch,以免漏掉的异常直接暴露给用户。

 

 

参考:http://msdn.microsoft.com/zh-cn/library/ms229014(v=VS.90).aspx