Visual Basic .NET中的異常處理簡介(下)
作者:Microsoft 非結構化異常處理 非結構化異常處理通過 Err 對象和以下三種語句來實現:On Error、Resume 和 Error。On Error 語句創建單個異常處理程序以捕捉發生的所有異常,您可以在以后改變處理程序的位置,但一次只能有一個處理程序。此方法可以跟蹤最近產生的異常和最近的異常處理程序的位置。在方法開始時,異常和異常處理程序的位置都設置為 Nothing。 要在代碼中生成運行時錯誤,請使用 Raise 方法。每次在錯誤處理例程中發生 Exit Sub、Exit Function、Exit Property、Resume 或 Resume Next 語句時,Err 對象的屬性都將重置為零或零長度字符串。在錯誤處理例程外部使用上述任何語句都不會重置其屬性。如果確實需要重置屬性,可以使用 Clear 方法重置 Err 對象。 Error 對象 Err 對象屬性的值由剛剛發生的錯誤決定。下表列出了該對象的屬性及其簡單說明。 屬性 說明 Description 對錯誤進行簡單說明的文本消息。 Helpcontext 整數,包含幫助文件中某個主題的上下文標識符。 Helpfile 字符串表達式,包含幫助文件的完全限定路徑。 LastDLL 由于調用動態鏈接庫 (DLL) 而產生的系統錯誤代碼。此 DLL 是發生錯誤之前最后調用的 DLL。 Number 指定錯誤的數值。 Source 字符串表達式,代表產生錯誤的對象或應用程序。
下面的示例顯示了如何在非結構化錯誤處理中使用上述某些屬性: On Error Resume Next Err.Clear Err.Raise(33333) Err.Description = "您沒有輸入數字!" MsgBox(Err.Number) MsgBox(Err.Description) Msg = "請按 F1 或“幫助”查看 " & Err.HelpFile & " 中有關以下幫助內容的" & _ "主題:" & Err.HelpContext MsgBox(Msg)
On Error GoTo 語句 On Error GoTo 語句啟用異常處理的某個例程,并指定該例程在此過程中的位置。它使用標簽或行號,指出特定異常處理例程在代碼中的位置。使用 -1 時,在過程內部禁用錯誤處理。使用 0 時,禁用當前異常。如果沒有 On Error 語句,并且在當前調用堆棧中所有方法均未處理異常,則發生任何運行時錯誤都將是致命的:執行過程停止并顯示錯誤消息。 下表列出了 On Error GoTo 語句可能使用的方法。 語句 任務 On Error Goto -1 將 Err 對象重置為 Nothing,從而在例程中禁用錯誤處理 On Error Goto 0 將最后的異常處理程序位置重置為 Nothing,從而禁用異常 On Error Goto <標簽名> 將指定標簽設置為異常處理程序的位置 On Error Resume Next 創建 Resume Next 行為,作為最近的異常處理程序的位置
Resume 和 Resume Next Resume 語句本身可以將控制權返回導致異常的語句。執行過程將返回到最初產生異常的那一行。 相比較而言,Resume Next 語句將在發生異常后恢復執行過程。該語句指定,在異常事件中,控制權將傳遞給緊接發生異常語句之后的語句。Resume Next 的使用可允許出現不太嚴重的失敗。引發錯誤的語句失敗,但應用程序將繼續執行,且允許用戶改正錯誤并繼續進行操作。與此類似,Resume <標簽> 將控制權傳遞給在其 line 參數中指定的標簽。確保行標簽與調用它的代碼位于相同的過程中,因為它不能跨函數使用。 Resume 在錯誤處理例程中必須單獨使用。它在這種例程的外部引發錯誤。 Error 語句 Visual Basic .NET 支持 Error 語句僅僅是為了保持向后兼容。在新代碼中,使用 Err 對象的 Raise 方法生成運行時錯誤。 非結構化異常處理示例 以下示例是非結構化錯誤處理的一種基本方法。當 FlawlessCode 遇到錯誤時,執行過程將轉移到 Whoops,它為用戶提供該錯誤的有關信息(主要包含在 Err 對象的 Description 屬性中的信息): Private Sub FlawlessCode() On Error Goto Whoops ' 代碼要做很多事情,不要過多 ' 地研究錯誤處理代碼。 Return Whoops: ' 為用戶提供錯誤信息。 MsgBox ("意外錯誤:" & Err.Description) Return End Sub
以下示例顯示了如何使用 Err 對象構造錯誤消息對話框。 Dim ErrorMessage as String ' 如果發生錯誤則構造錯誤消息。 On Error Resume Next Err.Raise (13) ' 生成“類型不匹配”錯誤。 ' 查看是否出現錯誤。如果是,則顯示消息。 If Err.Number <> 0 Then ErrorMessage = "錯誤 #" & Str(Err.Number) & " 原因是" _ & Err.Source & vbCrLf & Err.Description ' 將該消息顯示為關鍵消息。 MsgBox(ErrorMessage, MsgBoxStyle.Critical, "錯誤") End If 總結 到現在為止,您應該清楚地了解了結構化異常處理和非結構化異常處理之間的區別,以及 Visual Basic .NET 中結構化異常處理功能的優勢。通常情況下,結構化異常處理即可滿足您的需求,但在少數情況下仍然可能需要使用非結構化異常處理。 在確保異常得到處理的同時,不要過多地列舉它們,否則會導致性能下降。Try 結構是很有條理的,易于編寫且易于閱讀,它能生成有效的代碼。編寫處理一個或多個可能異常的代碼時,都應該使用該結構。此方法極其有效,您甚至愿意在正常情況下使用異常來控制邏輯流程。例如,替代 If 或 Select 語句。處理異常是很有效的,但應該到真正發生異常時使用。 下表列出了預定義的異常類及其起因和派生類。 表 1 異常類 產生原因 派生類 AppDomainUnloadedException 嘗試訪問未加載的應用程序域 無 ArgumentException 為方法提供的一個或多個參數無效 ArgumentNullException ArgumentOutOfRangeException ComponentModel.InvalidEnum ArgumentException DuplicateWaitObjectException ArithmeticException 在算法、強制類型轉換或轉換操作上發生錯誤 DivideByZeroException NotFiniteNumberException OverflowException ArrayTypeMismatchException 嘗試在數組中存儲錯誤類型的元素 無 BadImageFormatException DLL 或可執行程序的文件映像無效 無 CannotUnloadAppDomainException 嘗試卸載應用程序域失敗 無 ComponentModel.Design.Serialization. CodeDomSerializerException 產生序列化錯誤的行號信息 無 ComponentModel.LicenseException 無法為組件授予許可證 無 ComponentModel.WarningException 異常被作為警告而不是錯誤處理 無 Configuration.ConfigurationException 配置設置中發生錯誤 無 Configuration.Install.InstallException 在安裝過程的提交、回滾或卸載階段發生錯誤 無 ContextMarshalException 嘗試通過上下文范圍封送對象失敗 無 Data.DataException 使用 ADO.NET 組件時產生錯誤 Data.ConstraintException Data.DeletedRowInaccessibleException Data.DuplicateNameException Data.InRowChangingEventException Data.InvalidConstraintException Data.InvalidExpressionException Data.MissingPrimaryKeyException Data.NoNullAlllowedException Data.ReadOnlyException Data.RowNotInTableException Data.StringTypingException Data.TypedDataSetGeneratorException Data.VersionNotFoundException Data.DBConcurrencyException 在升級操作中,DataAdapter 確定受影響的行數等于零 無 Data.SqlClient.SqlException SQL Server 返回警告或錯誤 無 Data.SqlTypes.SqlTypeException Data.SqlTypes 的異常基類 Data.SqlTypes.SqlNullValueException Data.SqlTypes.SqlTruncateException Drawing.Printing. InvalidPrinterException 使用無效的打印機設置嘗試訪問打印機 無 EnterpriseServices. RegistrationException 檢測到注冊錯誤 無 EnterpriseServices.Serviced ComponentException 在運行的組件上檢測到錯誤 無 ExecutionEngineException 在公共語言運行時的執行引擎上存在內部錯誤 無 FormatException 參數的格式不符合調用方法的參數規定 Net.CookieException Reflection.CustomAttribute FormatException UriFormatException IndexOutofRangeException 嘗試訪問其索引在數組范圍之外的數組元素 無 InvalidCastException 無效的強制類型轉換或顯式轉換 無 InvalidOperationException 方法調用對于對象的當前狀態無效 Net.ProtocolViolationException Net.WebException ObjectDisposedException InvalidProgramException 程序包含無效的 Microsoft 中間語言或元數據 無 IO.InternalBufferOverflowException 內部緩沖區溢出 無 IO.IOException 發生 I/O 錯誤 IO.DirectoryNotFoundException IO.EndOfStreamException IO.FileLoadException IO.FileNotFoundException IO.PathTooLongException Management.ManagementException 管理錯誤 無 MemberAccessException 嘗試訪問類成員失敗 FieldAccessException MethodAccessException MissingFieldException MissingMemberException MissingMethodException MulticastNotSupportedException 嘗試組合兩個無法組合的代理類型實例,兩者的操作數都為非空引用 無 NotImplementedException 未執行要求的方法或操作 無 NotSupportedException 不支持所調用的方法,或者嘗試在不支持所調用函數的流中進行讀取、查找或寫入 PlatformNotSupportedException NullReferenceException 嘗試取消引用空對象引用 無 OutOfMemoryException 內存不足以完成執行程序 無 RankException 將具有錯誤維數的數組傳遞給方法 無 Reflection.AmbiguousMatch Exception 綁定方法時導致多個方法符合綁定條件 無 Reflection.ReflectionType LoadException Module.GetTypes 方法導致模塊中的一個或多個類無法加載 無 Resources.MissingManifest ResourceException 主要程序集不包含非特定語言的資源,但它們又是必需的,因為缺少合適的輔助程序集 無 Runtime.InteropServices. ExternalException 所有 COM 互操作異常和結構化異常處理異常的基本異常類型 ComponentModel.Design. CheckoutException ComponentModel.Win32Exception Data.OleDb.OleDbException Messaging.MessageQueueException Runtime.InteropServices.COMException Runtime.InteropServices.SEHException Web.HttpException Runtime.InteropServices. InvalidComObjectException 使用了無效的 COM 對象 無 Runtime.InteropServices. InvalidOleVariantTypeException 封送器遇到無法封送到管理代碼的變體類型參數 無 Runtime.InteropServices. MarshalDirectiveException 封送器遇到不支持的 MarshalAsAttribute 無 Runtime.InteropServices. SafeArrayRankMismatchException 傳入 SAFEARRAY 的名次與管理簽名中指定的名次不匹配 無 Runtime.InteropServices. SafeArrayTypeMismatchException 傳入 SAFEARRAY 的類型與管理簽名中指定的類型不匹配 無 Runtime.Remoting.RemotingException 遠程操作時發生錯誤 Runtime.Remoting.Remoting TimeOutException Runtime.Remoting.ServerException 用于在客戶端連接到無法產生異常的非 .NET 框架應用程序時傳遞異常 無 Runtime.Serialization. SerializationException 序列化或反序列化過程中發生錯誤 無 Security.Crytography. CryptographicException 加密操作過程中發生錯誤 Security.Cryptography. CryptographicUnexpected OperationException Security.Policy.PolicyException 策略禁止代碼運行 無 Security.SecurityException 檢測到安全性錯誤 無 Security.VerificationException 安全策略要求代碼的類型安全,而驗證程序無法驗證代碼是否類型安全 無 Security.XmlSyntaxException XML 分析時出現語法錯誤 無 ServiceProcess.TimeoutException 指定的超時已過期 無 StackOverflowException 待定的方法調用太多,導致執行堆棧溢出 無 Threading.SynchronizationLockException 在代碼的異步塊中調用同步方法 無 Threading.ThreadAbortException 調用 Abort 方法 無 Threading.ThreadInterruptedException 在 WaitSleepJoin 狀態時線程中斷 無 Threading.ThreadStateException 方法調用的無效 ThreadState 中的線程 無 TypeInitializationException 圍繞類初始化程序產生的異常而產生的包裝 無 TypeLoadException 類型加載失敗 DllNotFoundException EntryPointNotFoundException TypeUnloadedException 嘗試訪問已卸載的類 無 UnauthorizedAccessException 操作系統拒絕訪問,因為存在 I/O 錯誤或特定類型的安全性錯誤 無 Web.Services.Protocols.SoapException 在 SOAP 上調用 XML Web 服務方法而導致錯誤 Web.Services.Protocols. SoapHeaderException Xml.Schema.XmlSchemaException無 Xml.XmlException無 Xml.Xpath.XpathException 處理 Xpath 表達式時發生錯誤 無 Xml.Xsl.XsltException 處理可擴展樣式表語言 (XSL) 轉換時發生錯誤 System.Xml.Xsl.XsltCompileException
|