這遠不 及使用多個catch語句有吸引力,這是很脆弱的代碼:如果只是常規的修改了名 字,它就被破壞了。如果你移動了造成錯誤的函數調用,放到了一個共享的工具 函數中,它也被破壞了。在更深一層的堆棧上發生異常,就會使這樣的結構變得 更脆弱。
在深入討論這一話題前,讓我先附帶說明兩個不能做承諾的事 情。首先,異常並不能處理你所遇到的所有異常。這並不是一個穩固指導方法, 但我喜歡為錯誤條件拋出異常,這些錯誤條件如果不立即處理或者報告,可能會 在後期產生更嚴重的問題。例如,數據庫裡的數據完整性的錯誤,就應該生產一 個異常。這個問題如果忽略就只會越發嚴重。而像在寫入用戶的窗口位置失敗時 ,不太像是在後來會產生一系列的問題。返回一個錯誤代碼來指示失敗就足夠了 。
其次,寫一個拋出(throw)語句並不意味會在這個時間創建一個新的異 常類。我推薦創建更多的異常,而不是只有少數幾個常規的自然異常:很從人好 像在拋出異常時只對System.Exception情有獨鐘。可惜只只能提供最小的幫助信 息來處理調用代碼。相反,考慮創建一些必須的異常類,可以讓調用代碼明白是 什麼情況,而且提供了最好的機會來恢復它。
再說一遍:實際上要創建 不同的異常類的原則,而且唯一原因是讓你的用戶在寫catch語句來處理錯誤時 更簡單。查看分析這些錯誤條件,看哪些可以放一類裡,成為一個可以恢復錯誤 的行為,然後創建指定的異常類來處理這些行為。你的應用程序可以從一個文件 或者目錄丟失的錯誤中恢復過來嗎?它還可以從安全權限不足的情況下恢復嗎? 網絡資源丟失又會怎樣呢?對於這種遇到不同的錯誤,可能要采取不同的恢復機 制時,你應該為不同的行為創建新的異常類。
因此,現在你應該創建你 自己的異常類了。當你創建一個異常類時,你有很多責任要完成。你應該總是從 System.ApplicationException類派生你的異常類,而不是System.Exception類 。對於這個基類你不用添加太多的功能。對於不同的異常類,它已經具有可以在 不同的catch語句中處理的能力了。
但也不要從異常類中刪除任何東西。 ApplicationException 類有四個不同的構造函數:
// Default constructor
public ApplicationException( );
// Create with a message.
public ApplicationException( string );
// Create with a message and an inner exception.
public ApplicationException( string, Exception );
// Create from an input stream.
protected ApplicationException(
SerializationInfo, StreamingContext );
當你創建一個新的異 常類時,你應該創建這個四構造函數。不同的情況調用不同的構造方法來構造異 常。你可以委托這個工作給基類來實現:
public class MyAssemblyException :
ApplicationException
{
public MyAssemblyException( ) :
base( )
{
}
public MyAssemblyException( string s ) :
base( s )
{
}
public MyAssemblyException( string s,
Exception e) :
base( s, e )
{
}
protected MyAssemblyException(
SerializationInfo info, StreamingContext cxt ) :
base( info, cxt )
{
}
}