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
|