設計良好的應用處理異常和錯誤以防止應用崩潰。 本文描述處理和創建異常的最佳做法。
以下列表包含創建自己的異常和引發異常時應遵循的準則。
-
類的設計應使在正常使用中從不引發異常。 例如,FileStream 類提供可幫助確實是否已到達文件末尾的方法。 這避免了在讀取超過文件尾時引發的異常。 下面的示例顯示如何讀到文件尾。
class FileRead { public void ReadAll(FileStream fileToRead) { // This if statement is optional // as it is very unlikely that // the stream would ever be null. if (fileToRead == null) { throw new System.ArgumentNullException(); } int b; // Set the stream position to the beginning of the file. fileToRead.Seek(0, SeekOrigin.Begin); // Read each byte to the end of the file. for (int i = 0; i < fileToRead.Length; i++) { b = fileToRead.ReadByte(); Console.Write(b.ToString()); // Or do something else with the byte. } } }
-
引發異常,而不是返回錯誤代碼或 HRESULT。
-
對于極其常見的錯誤案例,返回 null 而不是引發異常。 極其常見的錯誤案例可被視為常規控制流。 通過在這些情況下返回 null,可最大程度地減小對應用的性能產生的影響。
-
在大多數情況下,使用預定義的異常類型。 引入新異常類,使程序員能夠根據異常類在代碼中采取不同的操作。
-
如果根據對象的當前狀態,屬性集或方法調用不適當,則會引發 InvalidOperationException 異常。
-
如果傳遞的參數無效,則會引發 ArgumentException 異常或派生自 ArgumentException 的類。
-
對于大多數應用,從 Exception 類派生自定義異常。從 ApplicationException 類派生并沒有很大意義。
-
以“Exception”一詞作為異常類名的結尾。 例如:
-
在 C# 和 C++ 中,創建自己的異常類別時至少使用三種公共構造函數:默認構造函數、采用字符串消息的構造函數和采用字符串消息和內部異常的構造函數。 有關示例,請參見如何:創建用戶定義的異常。
-
Exception() ,它使用默認值。
-
Exception(String) ,它接受字符串消息。
-
Exception(String, Exception) ,它接受字符串消息和內部異常。
-
-
當創建用戶定義的異常時,必須確保異常的元數據對遠程執行的代碼可用,包括當異常跨應用域發生時。 例如,假設應用域 A 創建應用域 B,后者執行引發異常的代碼。 應用域 A 若想正確捕獲和處理異常,它必須能夠找到包含應用域 B 所引發的異常的程序集。 如果包含應用域 B 引發的異常的程序集位于應用域 B 的應用程序基目錄下,而不是位于應用域 A 的應用程序基目錄下,則應用域 A 將無法找到異常,并且公共語言運行時將引發 FileNotFoundException 異常。 為避免此情況,可以兩種方式部署包含異常信息的程序集:
-
將程序集放在兩個應用域共享的公共應用程序基中。
- 或 -
-
如果兩個應用域不共享一個公共應用程序基,則用強名稱為包含異常信息的程序集簽名并將其部署到全局程序集緩存中。
-
-
在每個異常中都包含一個本地化描述字符串。 用戶看到的錯誤消息派生自引發的異常的描述字符串,而不是派生自異常類。
-
通過編程方式使用正確的錯誤消息(包括結束標點)。 在異常的描述字符串中,每個句子都應以句號結尾。 例如,“記錄表已溢出。”將是正確的描述字符串。
-
為編程訪問提供 Exception 屬性。 僅當存在附加信息有用的編程方案時,才在異常中包含附加信息(不包括描述字符串)。
-
堆棧跟蹤從引發異常的語句開始,到捕獲異常的 catch 語句結束。 當決定在何處放置 throw 語句時需考慮這一點。
-
使用異常生成器方法。 類從其實現中的不同位置引發同一異常是常見的情況。 為避免過多的代碼,應使用幫助器方法創建異常并將其返回。 例如:
class FileReader { private string fileName; public FileReader(string path) { fileName = path; } public byte[] Read(int bytes) { byte[] results = FileUtils.ReadFromFile(fileName, bytes); if (results == null) { throw NewFileIOException(); } return results; } FileReaderException NewFileIOException() { string description = "My NewFileIOException Description"; return new FileReaderException(description); } }
或者,使用異常的構造函數生成異常。 這更適合全局異常類,例如 ArgumentException。
-
引發異常時清理中間結果。 當異常從方法引發時,調用方應能夠假定沒有副作用。
- 來源:http://msdn.microsoft.com/zh-cn/library/seyhszts.aspx?cs-save-lang=1&cs-lang=csharp#code-snippet-1
文章列表