標籤:environ exce 方式 engine out ati test try 執行
第 7 章:異常
異常與各種物件導向語言整合得非常好。
異常增強了 API 的一致性。
在用傳回值來報告錯誤時,錯誤處理的代碼與可能會發生錯誤的代碼距離總是很近。
更容易使錯誤處理的帶碼全域化。
錯誤碼很容易被忽略,而且經常會被忽略。
異常可以包含豐富的資訊來對錯誤的原因加以描述。
異常允許使用者定義未處理異常的處理常式。
異常可以包含豐富的資訊來對錯誤額原因加以描述。
異常允許使用者定義未處理異常的處理常式。
異常有助於檢測。
7.1 拋出異常
不要返回錯誤碼。
要通過拋出異常的放回來報告操作失敗。
考慮在代碼遇到嚴重問題且無法繼續安全地執行時,通過調用 System.Environment.FailFast 來終止進程,而不要拋出異常。
不要在正常的控制流程中使用異常,如果能夠避免的話。
考慮拋出異常可能會對效能造成的影響。對大多數的應用程式來說,每秒拋出 100 個異常很可能會嚴重地影響效能。
要為所有的異常撰寫文檔,並把它們作為契約的一部分 - 如果異常是因為在調用公有成員時違反了它的契約而拋出的(非系統失敗)。
不要讓公有成員根據某個選項來決定是否拋出異常。
不要把異常用作公有成員的傳回值或輸出參數。
考慮使用輔助方法來建立異常。
不要在異常過濾程式中拋出異常。
避免顯式地從 finally 代碼塊中拋出異常。隱式地拋出異常,即在調用其它方法時由其它方法拋出異常,是可以接受的。
7.2 為拋出的異常選擇合適的類型
不要為了通報使用錯誤而建立新的異常類型。在這種情況下應該拋出架構中已有的異常。
考慮為程式錯誤建立並拋出自訂的異常 - 如果對它的處理方式和對其它異常的處理方式有所不同。否則,應該拋出已有的異常。
不要建立新的異常類型 - 如果對該錯誤的處理和對架構中已有異常的並沒有什麼不同。在這種情況下應該拋出架構中已有的異常。
要建立新的異常類型來傳達獨一無二的程式錯誤 - 如果不能通過架構中已有的異常來傳達該錯誤。
避免設計出會導致系統失敗的 API。如果此類失敗可能會發生,那麼在發生系統失敗時應該調用 Environment.FailFast,而不應該拋出異常。
不要僅僅為了擁有自己的異常而建立並使用新的異常。
要使用合理的、最具針對性(最底層衍生類別)的異常。
要在拋出異常時為開發人員提供豐富而有意義的錯誤訊息。
要確保異常訊息的文法正確無誤。
要確保異常訊息中的每個句子都有句號。
避免在異常訊息這種使用問號和驚歎號。
不要在沒有得到許可的情況下在異常訊息中泄漏安全訊息。
考慮把組件拋出的異常訊息本地化 - 如果想讓沐浴為其它語言的開發人員也能使用組件。
不要在架構的代碼捕獲具體類型不確定的異常(比如 System.Exception、System.SystemException,等等)時,把錯誤吞了。
避免在應用程式的代碼中,在捕獲具體類型不確定的異常(比如 System.Exception、System.SystemException,等等)時,把錯誤吞了。
不要把任何特殊的異常排除在外 - 如果編寫 catch 代碼塊的目的就是為了轉移異常。
考慮捕獲特定類型的異常 - 如果確實理解該異常在具體環境中產生的原因,並能對錯誤做出適當的反應。
不要捕獲不應該捕獲的異常。通常應該允許異常沿著調用棧向上遊傳遞。
要在進行清理工作時使用 try-finally,避免使用 try-catch。對精心編寫的異常代碼來說,try-finally 的使用頻率要比 try-catch 高得多。
要在捕獲並重新拋出異常時使用空的 throw 語句。這是保持異常調用棧不變的最好方法。
不要用無參數的 catch 塊來處理不符合 CLS 規範 規範的異常(不是派生自 System.Exception 的異常)。
考慮對較低層次拋出的異常進行適當地封裝 - 如果較低層次的異常在較高層次的運行環境中沒有什麼意義。
避免捕獲並封裝具體類型不確定的異常。
要在對異常進行封裝時為其指定內部異常。
7.3 標準異常類型的使用
不要拋出 System.Exception 或 System.SystemExceptio 異常。
不要在架構代碼中捕獲 System.Exception 或 System.SystemException 異常,除非打算重新拋出。
避免捕獲 System.Exception 或 Systen.SystemException 異常,除非是在頂層的異常處理器中。
不要拋出 System.ApplicationException 或從它派生新類。
要拋出 InvalidaOperationException 異常 - 如果對象處於不正確的狀態。
要在使用者傳入無效參數時拋出 ArgumentException 異常或其子類型。如果可以的話,要盡量使用位於繼承層次末尾的異常類型。
要在拋出 ArgumentException 異常或其子類時設定 ParamName 屬性。
要在屬性的 setter 中,以 value 作為 value 隱式參數的名字。
不要讓公用 API 顯式地或隱式地拋出 NullReferenceException、AccessViolationException 或 IndexOutOfRangeException 異常。這些異常時專門留給執行引擎來拋出的,大多數情況下它們表示代碼存在缺陷。
不要顯式地拋出 StackOverflowException 異常。應該只有 CLR 才能顯式地拋出該異常。
不要捕獲 StackOverflowException 異常。
不要顯式地拋出 OutOfMemoryException 異常。應該只有 CLR 才能拋出異常。
不要顯示地拋出 ComException、ExecutingEngineException 及 SEHException 異常,應該只有 CLR 才能拋出這些異常。
7.4 自訂異常的設計
要從 System.Exception 或其它常用的異常基類派生新的異常。
避免太深的繼承層次。
要在命名異常類時使用“Exception”尾碼。
要使異常可序列化。為了使異常能夠在跨應用程式定義域和跨遠程邊界時仍能正常使用,這樣做是必須的。
要為所有的異常(至少)提供下面這些常用的建構函式。
要通過 ToString 的一個覆蓋方法來報告與安全性有關的訊息,前提是必須先獲得相應的許可。
要把與安全性有關的資訊儲存在私人的異常狀態中,並確保只有可信賴的代碼才能得到該資訊。
考慮為異常定義屬性,這樣就能從程式中取得除了訊息字串之外與異常有關的額外資訊。
7.5 異常與效能
不要因異常可能對效能造成負面影響而使用錯誤碼。
考慮在成員中使用 Tester-Doer 模式來避免因異常而引起的效能問題 - 如果成員在常用情境中都可能拋出異常。
考慮在成員中使用 Try-Parse 模式來避免因異常而引起的效能問題,如果成員在常用代碼中都可能會拋出異常。
要在實現 Try-Parse 模式時使用“Try”首碼,並用布爾類型作為方法的傳回型別。
要為每個使用 Try-Parse 模式的方法提供一個會拋出異常的對應成員。
《.NET 設計規範》第 7 章:異常