On Error 语句 (Visual Basic)
启用错误处理例程,并指定例程在过程中的位置;还可用于禁用错误处理例程。 On Error
语句在非结构化错误处理中使用,可用于替代结构化异常处理。 结构化异常处理内置在 .NET 中,通常更加高效,因此在应用程序中处理运行时错误时建议采用这种处理。
如果不进行错误处理或异常处理,则发生的任何运行时错误都是严重错误:会显示错误消息并停止执行。
注意
Error
关键字也可在 Error 语句中使用,支持这种做法是为了实现后向兼容性。
语法
On Error { GoTo [ line | 0 | -1 ] | Resume Next }
组成部分
术语 | 定义 |
---|---|
GoTo 行 |
启用从必需 line 参数中所指定的行开始的错误处理例程。 line 参数是任何行标签或行号。 如果发生运行时错误,则控制会转移到指定行,从而使错误处理程序处于活动状态。 指定行必须与 On Error 语句处于同一过程中,否则会发生编译时错误。 |
GoTo 0 |
在当前过程中禁用已启用的错误处理程序,并将它重置为 Nothing 。 |
GoTo -1 |
在当前过程中禁用已启用的异常,并将它重置为 Nothing 。 |
Resume Next |
指定在发生运行时错误时,控件会转到紧跟在发生错误的语句后的语句,执行会从该点继续进行。 访问对象时使用此形式,而不是 On Error GoTo 。 |
注解
注意
建议尽可能在代码中使用结构化异常处理,而不是使用非结构化异常处理和 On Error
语句。 有关详细信息,请参阅 Try...Catch...Finally 语句。
“已启用”错误处理程序是由 On Error
语句开启的处理程序。 “活动”错误处理程序是正在处理错误的已启用处理程序。
如果在错误处理程序处于活动状态时(介于错误发生与 Resume
、Exit Sub
、Exit Function
或 Exit Property
语句之间)发生某个错误,则当前过程的错误处理程序无法处理该错误。 控制会返回到调用过程。
如果调用过程具有已启用错误处理程序,则会激活它以处理错误。 如果调用过程的错误处理程序也处于活动状态,则控制会沿着以前的调用过程向回传递,直到找到已启用但非活动的错误处理程序。 如果未找到此类错误处理程序,则在实际发生错误的位置处,错误是严重错误。
每次错误处理程序将控制传递回某个调用过程时,该过程会成为当前过程。 错误由任何过程中的错误处理程序进行处理后,执行会在当前过程中由 Resume
语句指定的位置处继续进行。
注意
错误处理例程不是 Sub
过程或 Function
过程。 它是由行标签或行号标记的代码部分。
Number 属性
错误处理例程依赖于 Err
对象的 Number
属性中的值来确定错误的原因。 例程应先测试或保存 Err
对象中的相关属性值,然后才能发生任何其他错误或调用可能导致错误的过程。 Err
对象中的属性值仅反映最近的错误。 与 Err.Number
关联的错误消息包含在 Err.Description
中。
Throw 语句
使用 Err.Raise
方法引发的错误会将 Exception
属性设置为 Exception 类的新创建实例。 为了支持引发派生异常类型的异常,语言中支持 Throw
语句。 此语句采用单个参数,该参数是要引发的异常实例。 下面的示例演示如何将这些功能与现有异常处理支持一起使用:
On Error GoTo Handler
Throw New DivideByZeroException()
Handler:
If (TypeOf Err.GetException() Is DivideByZeroException) Then
' Code for handling the error is entered here.
End If
请注意,On Error GoTo
语句会捕获所有错误,而不考虑异常类。
On Error Resume Next
On Error Resume Next
会使执行继续运行紧跟在导致运行时错误的语句后的语句,或是继续运行紧跟在包含 On Error Resume Next
语句的过程的最近一次调用后的语句。 此语句允许在出现运行时错误的情况下继续执行。 可以将错误处理例程放置在发生错误的位置,而不是将控制转移到过程中的其他位置。 On Error Resume Next
语句会在调用其他过程时变为非活动状态,因此如果希望在该例程中进行内联错误处理,则应在每个调用的例程中执行 On Error Resume Next
语句。
注意
在处理访问其他对象期间生成的错误时,On Error Resume Next
构造可能比 On Error GoTo
更可取。 每次与对象交互后检查 Err
可消除有关代码访问的对象的歧义。 可以确定哪个对象将错误代码置于 Err.Number
中,以及哪个对象最初生成了错误(Err.Source
中指定的对象)。
On Error GoTo 0
On Error GoTo 0
在当前过程中禁用错误处理。 它不会将行 0 指定为错误处理代码的开头,即使过程包含编号为 0 的行。 如果没有 On Error GoTo 0
语句,则退出过程时会自动禁用错误处理程序。
On Error GoTo -1
On Error GoTo -1
在当前过程中禁用异常。 它不会将行 -1 指定为错误处理代码的开头,即使过程包含编号为 -1 的行。 如果没有 On Error GoTo -1
语句,则退出过程时会自动禁用异常。
若要防止错误处理代码在未发生错误时运行,请紧挨在错误处理例程前面放置 Exit Sub
、Exit Function
或 Exit Property
语句,如下面的片段所示:
Public Sub InitializeMatrix(ByVal Var1 As Object, ByVal Var2 As Object)
On Error GoTo ErrorHandler
' Insert code that might generate an error here
Exit Sub
ErrorHandler:
' Insert code to handle the error here
Resume Next
End Sub
此处,错误处理代码跟踪 Exit Sub
语句后面,并位于 End Sub
语句前面,以将它与过程流分开。 可以将错误处理代码置于过程中的任何位置。
未捕获的错误
当对象作为可执行文件运行时,对象中的未捕获错误会返回到控制应用程序。 在开发环境中,仅当设置了正确选项时,未捕获的错误才会返回到控制应用程序。 有关调试期间应设置的选项、如何设置选项以及主机是否可以创建类的说明,请参阅主机应用程序的文档。
如果创建访问其他对象的对象,应尝试处理它们传递回的任何未经处理的错误。 如果你无法处理,则将 Err.Number
中的错误代码映射到你自己的错误之一,然后将它们传递回对象的调用方。 应通过将错误代码添加到 VbObjectError
常量来指定错误。 例如,如果错误代码为 1052,请按如下所示分配它:
Err.Number = vbObjectError + 1052
注意
调用 Windows动态链接库 (DLL) 期间的系统错误不会引发异常,无法使用 Visual Basic 错误捕获进行捕获。 调用 DLL 函数时,应检查每个返回值是成功还是失败(根据 API 规范),如果失败,则检查 Err
对象的 LastDLLError
属性中的值。
示例
此示例首先使用 On Error GoTo
语句指定错误处理例程在过程中的位置。 在该示例中,尝试除以零会生成错误号 6。 错误在错误处理例程中进行处理,控制随后会返回到导致错误的语句。 On Error GoTo 0
语句会关闭错误捕获。 On Error Resume Next
语句随后用于延迟错误捕获,以便可以确定下一个语句生成的错误的上下文。 请注意,Err.Clear
用于在处理错误后清除 Err
对象的属性。
Public Sub OnErrorDemo()
On Error GoTo ErrorHandler ' Enable error-handling routine.
Dim x As Integer = 32
Dim y As Integer = 0
Dim z As Integer
z = x / y ' Creates a divide by zero error
On Error GoTo 0 ' Turn off error trapping.
On Error Resume Next ' Defer error trapping.
z = x / y ' Creates a divide by zero error again
If Err.Number = 6 Then
' Tell user what happened. Then clear the Err object.
Dim Msg As String
Msg = "There was an error attempting to divide by zero!"
MsgBox(Msg, , "Divide by zero error")
Err.Clear() ' Clear Err object fields.
End If
Exit Sub ' Exit to avoid handler.
ErrorHandler: ' Error-handling routine.
Select Case Err.Number ' Evaluate error number.
Case 6 ' Divide by zero error
MsgBox("You attempted to divide by zero!")
' Insert code to handle this error
Case Else
' Insert code to handle other situations here...
End Select
Resume Next ' Resume execution at the statement immediately
' following the statement where the error occurred.
End Sub
要求
程序集:Visual Basic 运行时库(在 Microsoft.VisualBasic.dll 中)