詳解C#編程中異常的創立和激發和異常處置。本站提示廣大學習愛好者:(詳解C#編程中異常的創立和激發和異常處置)文章只能為提供參考,不一定能成為您想要的結果。以下是詳解C#編程中異常的創立和激發和異常處置正文
創立和激發異常
異經常使用於指導在運轉法式時產生了毛病。此時將創立一個描寫毛病的異常對象,然後應用 throw 症結字“激發”該對象。然後運轉時搜刮最兼容的異常處置法式。
當存鄙人列一種或多種情形時,法式員應激發異常:
辦法沒法完成個中界說的功效。
例如,假如辦法的參數具有沒有效值:
static void CopyObject(SampleClass original) { if (original == null) { throw new System.ArgumentException("Parameter cannot be null", "original"); } }
依據對象的狀況,對某個對象停止不恰當的挪用。
一個示例能夠測驗考試對只讀文件履行寫操作。在對象狀況不許可某項操作的情形下,激發 InvalidOperationException 的一個實例或基於此類的派生類的對象。以下為激發 InvalidOperationException 對象的辦法的示例:
class ProgramLog { System.IO.FileStream logFile = null; void OpenLog(System.IO.FileInfo fileName, System.IO.FileMode mode) {} void WriteLog() { if (!this.logFile.CanWrite) { throw new System.InvalidOperationException("Logfile cannot be read-only"); } // Else write data to the log and return. } }
辦法的參數招致了異常。
在此情形下,應捕捉原始異常並創立一個 ArgumentException 實例。原始異常應作為 InnerException 參數傳遞給 ArgumentException 的結構函數:
static int GetValueFromArray(int[] array, int index) { try { return array[index]; } catch (System.IndexOutOfRangeException ex) { System.ArgumentException argEx = new System.ArgumentException("Index is out of range", "index", ex); throw argEx; } }
異常包括一個名為 StackTrace 的屬性。此字符串包括以後挪用客棧上的辦法的稱號,和為每一個辦法激發異常的地位(文件名和行號)。 StackTrace 對象由公共說話運轉時 (CLR) 從 throw 語句點開端主動創立,是以必需從客棧跟蹤的開端點激發異常。
一切異常都包括一個名為 Message 的屬性。應當設置此字符串來說明產生異常的緣由。留意,不該將平安敏感信息放在新聞文本中。除 Message 以外,ArgumentException 還包括一個名為 ParamName 的屬性,應將該屬性設置為招致激發異常的參數的稱號。關於屬性設置器,ParamName 應設置為 value。
公共的受掩護辦法應在其沒法完成預期功效時激發異常。激發的異常類應當是相符毛病前提的最確實的可用異常。這些異常應編寫為類功效的一部門,派生類或對原始類的更新應保存雷同的行動,以完成向後兼容性。
激發異常時要防止的情形
下表肯定了在激發異常時要防止的做法:
界說異常類
法式可以激發 System 定名空間中的預界說異常類(後面注明的情形除外),或經由過程從 Exception 派生來創立它們本身的異常類。派生類至多應界說四個結構函數:一個是默許結構函數,一個用來設置新聞屬性,一個用來設置 Message 屬性和 InnerException 屬性。第四個結構函數用於序列化異常。新異常類應當可序列化。例如:
public class InvalidDepartmentException : System.Exception { public InvalidDepartmentException() : base() { } public InvalidDepartmentException(string message) : base(message) { } public InvalidDepartmentException(string message, System.Exception inner) : base(message, inner) { } // A constructor is needed for serialization when an // exception propagates from a remoting server to the client. protected InvalidDepartmentException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { } }
僅當新屬性供給的數據有助於處理異常時,才應將其添加到異常類。假如向派生的異常類添加了新屬性,則應重寫 ToString() 以前往添加的信息。
異常處置
C# 法式員可以使用 try 塊對能夠受異常影響的代碼停止分區。聯系關系的 catch 塊用於處置任何成果異常。一個包括代碼的 finally 塊,不管 try 塊中能否激發異常(例如,釋放在 try 塊平分配的資本),這些代碼都邑運轉。一個 try 塊須要一個或多個聯系關系的 catch 塊或一個 finally 塊,或二者。
以下示例給出了一個 try-catch 語句,一個 try-finally 語句,和一個 try-catch-finally 語句。
try { // Code to try goes here. } catch (SomeSpecificException ex) { // Code to handle the exception goes here. // Only catch exceptions that you know how to handle. // Never catch base class System.Exception without // rethrowing it at the end of the catch block. } try { // Code to try goes here. } finally { // Code to execute after the try block goes here. } try { // Code to try goes here. } catch (SomeSpecificException ex) { // Code to handle the exception goes here. } finally { // Code to execute after the try (and possibly catch) blocks // goes here. }
不帶有 catch 或 finally 塊的 try 塊將招致編譯器毛病。
Catch 塊
catch 塊可以指定要捕獲的異常的該類型。類型標准稱為“異常挑選器”。異常類型應從 Exception 派生出來。普通而言,不會將 Exception 指定為異常挑選器,除非您懂得若何處置 try 塊中能夠激發的一切異常,或許您在 catch 塊中包含了 throw 語句。
具有分歧異常挑選器的多個 catch 塊可以串連在一路。多個 catch 數據塊的盤算次序是在代碼中從頂部究竟部,然則,關於所激發的每一個異常,都只履行一個 catch 數據塊。與指定的精確類型或其基類最為婚配的第一個 catch 塊被履行。假如 catch 塊沒有指定婚配異常挑選器,則 catch 塊就不具有選定的挑選器(假如語句有的話)。須要將帶有最詳細的(即派生水平最高的)異常類的 catch 塊放在最後面。
當以下前提為真時,應當捕獲異常:
對激發異常的緣由有詳細的懂得,並可完成特定的恢復,例如,在捕捉 FileNotFoundException 對象時提醒用戶輸出新的文件名。
可以新建一個更詳細的異常並激發該異常。
int GetInt(int[] array, int index) { try { return array[index]; } catch(System.IndexOutOfRangeException e) { throw new System.ArgumentOutOfRangeException( "Parameter index is out of range."); } }
願望在將異常傳遞出去停止額定處置前部門地處置異常。鄙人面的示例中,catch 塊用於在再次激發異常之前,向毛病日記添加條目。
try { // Try to access a resource. } catch (System.UnauthorizedAccessException e) { // Call a custom error logging procedure. LogError(e); // Re-throw the error. throw; }
Finally 塊
可使用 finally 塊清算在 try 塊中履行的操作。假如存在,finally 塊將在最初履行,在 try 塊和任何婚配 catch 的塊以後履行。不論能否激發異常或許能否找到與異常類型婚配的 catch 塊,finally 一直運轉。
可使用 finally 塊釋放資本(如文件流、數據庫銜接和圖形句柄),而不消期待由運轉時中的渣滓收受接管器來完成對象。
鄙人面的示例中,應用 finally 塊封閉在 try 塊中翻開的文件。留意,在封閉文件之前要檢討該文件句柄的狀況。假如 try 塊沒法翻開文件,則文件句柄仍具有值 null,而且 finally 塊不會測驗考試封閉它。或許,假如在 try 塊中勝利翻開該文件,則 finally 塊將封閉翻開的文件。
System.IO.FileStream file = null; System.IO.FileInfo fileinfo = new System.IO.FileInfo("C:\\file.txt"); try { file = fileinfo.OpenWrite(); file.WriteByte(0xF); } finally { // Check for null because OpenWrite might have failed. if (file != null) { file.Close(); } }