知道何時設置 try/catch 塊。例如,可以以編程方式檢查可能發生的條件,而不使用異常處理。在其他情況下,使用異常處理捕捉錯誤條件是適當的。 下面的示例使用 if 語句檢查連接是否關閉。如果連接未關閉,可以使用此方法而不是引發異常。
[visual basic] if conn.state <> connectionstate.closed then conn.close() end if [c#] if(conn.state != connectionstate.closed) conn.close(); 在下面的示例中,如果連接未關閉,則引發異常。
[visual basic] try conn.close() catch ex as invalidoperationexception 'do something with the error or ignore it. end try [c#] try { conn.close(); } catch(invalidoperationexception ex) { //do something with the error or ignore it. } 所選擇的方法依賴于預計事件發生的頻率。如果事件確實是異常的并且是一個錯誤(如意外的文件尾),則使用異常處理比較好,因為正常情況下執行的代碼更少。如果事件是例行發生的,使用編程方法檢查錯誤比較好。在此情況下,如果發生異常,將需要更長的時間處理。
在可潛在生成異常的代碼周圍使用 try/finally 塊,并將 catch 語句集中在一個位置。以這種方式,try 語句生成異常,finally 語句關閉或釋放資源,而 catch 語句從中心位置處理異常。 始終按從最特定到最不特定的順序對 catch 塊中的異常排序。此方法在將特定異常傳遞給更常規的 catch 塊之前處理該異常。 以“exception”這個詞作為異常類名的結尾。例如: [visual basic] public class employeelistnotfoundexception inherits exception [c#] public class myfilenotfoundexception : applicationexception { } 當創建用戶定義的異常時,必須確保異常的元數據對遠程執行的代碼可用,包括當異常跨應用程序域發生時。例如,假設應用程序域 a 創建應用程序域 b,后者執行引發異常代碼。應用程序域 a 若想正確捕捉和處理異常,它必須能夠找到包含應用程序域 b 引發的異常的程序集。如果包含應用程序域 b 引發的異常的程序集位于應用程序域 b 的應用程序基下,而不是位于應用程序域 a 的應用程序基下,則應用程序域 a 將無法找到異常,公共語言運行庫將引發 filenotfoundexception。為避免此情況,可以兩種方式部署包含異常信息的程序集: 將程序集放在兩個應用程序域共享的公共應用程序基中,或者 如果兩個應用程序域不共享一個公共應用程序基,則用強名稱給包含異常信息的程序集簽名并將其部署到全局程序集緩存中。 在 c# 和 c++ 的托管擴展中創建您自己的異常類時,至少使用三個公共構造函數。有關示例,請參閱使用用戶定義的異常。 在大多數情況下,使用預定義的異常類型。僅為編程方案定義新異常類型。引入新異常類,使程序員能夠根據異常類在代碼中采取不同的操作。 不要從 exception 基類派生用戶定義的異常。對于大多數應用程序,從 applicationexception 類派生自定義異常。 在每個異常中都包含一個本地化描述字符串。當用戶看到錯誤信息時,該信息從引發的異常的描述字符串派生,而不是從異常類派生。 使用語法上正確的錯誤信息(包括結束標點符號)。在異常的描述字符串中,每個句子都應以句號結尾。 為編程訪問提供 exception 屬性。僅當存在附加信息有用的編程方案時,才在異常中包含附加信息(不包括描述字符串)。 對非常常見的錯誤情況返回空。例如,如果沒找到文件,file.open 返回空;但如果文件被鎖定,則引發異常。 類的設計應使在正常使用中從不引發異常。例如,filestream 類公開另一種確定是否已到達文件尾的方法。這避免了在讀取超過文件尾時引發的異常。下面的示例顯示如何讀到文件尾。 [visual basic] class fileread sub open() dim stream as filestream = file.open("myfile.txt", filemode.open) dim b as byte
' readbyte returns -1 at eof. while b = stream.readbyte() <> true ' do something. end while end sub end class [c#] class fileread { void open() { filestream stream = file.open("myfile.txt", filemode.open); byte b;
// readbyte returns -1 at eof. while ((b == stream.readbyte()) != true) { // do something. } } } 如果根據對象的當前狀態,屬性集或方法調用不適當,引發 invalidoperationexception。 如果傳遞錯誤的參數,引發 argumentexception 或從 argumentexception 派生的類。 堆棧跟蹤從引發異常的語句開始,到捕捉異常的 catch 語句結束。當決定在何處放置 throw 語句時需考慮這一點。 使用異常生成器方法。類從其實現中的不同位置引發同一異常是常見的情況。為避免過多的代碼,應使用幫助器方法創建異常并將其返回。例如: [visual basic] class file private filename as string
public function read(bytes as integer) as byte() if not readfile(handle, bytes) then throw newfileioexception() end if end function 'read
function newfileioexception() as fileexception dim description as string = __unknown ' build localized string, including filename. return new fileexception(description) ' end function 'newfileioexception end class 'file [c#] class file { string filename; public byte[] read(int bytes) { if (!readfile(handle, bytes)) throw newfileioexception(); } fileexception newfileioexception() { string description = // build localized string, including filename. return new fileexception(description); } } 或者,使用異常的構造函數生成異常。這更適合全局異常類,如 argumentexception。