【问题标题】:Why would you ever use "On Error Goto 0"?为什么你会使用“On Error Goto 0”?
【发布时间】:2012-04-02 20:37:19
【问题描述】:

您为什么会在 VB6 应用程序中使用 "On Error Goto 0"

此语句关闭错误处理程序,这意味着任何错误都会导致应用程序崩溃。为什么这会是可取的?

【问题讨论】:

  • 嗯,这当然是实现fail-fast的一种方式
  • 我没有安装 VB6,但大概任何转到不存在标签的 Goto 语句都会使应用程序崩溃。
  • 这听起来像是来自某人的评论并且无论如何都会弹出一个带有相同错误的 MsgBox。
  • 完全不正确。它通常与 On Error Resume Next 和对 Err.Number 的测试配对以进行内联结构化错误处理。
  • @CraigJ:请记住,错误处理是针对that procedure (and children) only。 “关闭它”不是全局的,它允许父级处理错误。

标签: vb6 error-handling


【解决方案1】:

在 VB6 中,您可以指定希望稍后在例程中由特定代码处理错误:

Sub Bar()
    On Error Goto MyHandler
    ...
    ...some code that throws an error...
    ...
    Exit Sub
MyHandler:
    ...some error handler code (maybe pops up a dialog)
End Sub

然而,抛出错误的代码可能是本地化的,并且您不希望例程中的所有其余代码都使用相同的处理程序。在这种情况下,您将使用“On Error Goto 0”,如下所示:

Sub Bar()
    ...
    On Error Goto MyHandler
    ...some code that throws an error...
    On Error Goto 0
    ...
    ...
    Exit Sub
MyHandler:
    ...some error handler code (maybe pops up a dialog)
End Sub

现在您已经有效地将错误处理范围限定为仅在该特定代码行失败时才执行。

通过调用“On Error Goto 0”,您并不是说您希望应用程序立即崩溃。您只是说您想取消注册您可能在例程中较早设置的任何错误处理程序;错误会像往常一样通过调用堆栈向上传递给调用例程。

【讨论】:

  • 您还将错误处理向上传递给调用过程
  • 如果当前过程已经在调用栈的底部怎么办?那你能看出它有什么用吗?因为此时的错误会使应用程序崩溃。
  • Craig,这与一开始就没有设置错误处理程序没有什么不同。默认情况下,如果没有任何类型的错误处理,应用程序将崩溃。即使在顶层,明确哪些代码行具有“活动”错误处理,然后再次将其关闭,这通常也是有意义的。假设我们只希望在某段代码失败时进行日志记录。之后我们应该取消注册错误处理程序。错误处理并不总是为了防止崩溃。它可以用于记录或清理系统资源。崩溃可能是期望的(有意识的)行为。
【解决方案2】:

它只关闭 CURRENT 过程中的错误处理。如果调用过程中有错误处理程序,它将捕获任何未处理的异常。 VB 不断向上调用堆栈,直到找到错误处理程序。如果它没有找到任何 THEN 将导致运行时错误。

举个例子——也许你有一个包装函数,它调用了一些可能引发异常的第三方实用程序。不是在包装函数中处理异常,而是在其中放置 On Error Goto 0。因此,包装函数的调用者将获得传递给它的异常,并希望以适当的方式处理它。

【讨论】:

    【解决方案3】:

    由于用文字描述似乎很笨拙,这里有一些示例说明您可以在哪些地方使用On Error GoTo 0 进行本地化、结构化的错误处理。

    第一个是类(“MicroDOM”)中的Property Get,它基于子类集合的层次结构实现轻量级 DOM。在这种情况下,我们希望尝试通过名称而不是索引来引用丢失的 Child 以创建一个空的(没有属性或子项)子项:

    Public Property Get Child(ByVal Key As Variant) As MicroDOM
        If mChildren Is Nothing Then
            Set mChildren = New Collection
        End If
        On Error Resume Next
        Set Child = mChildren(Key)
        If Err Then
            On Error GoTo 0
            If VarType(Key) = vbString Then
                Key = Trim$(Key)
                Set Child = New MicroDOM
                Child.Key = Key
                mChildren.Add Child, Key
            Else
                Err.Raise 9 'Subscript error as thrown by the Collection.
            End If
        End If
    End Property
    

    第二个是内联代码,如果文件存在则删除:

    On Error Resume Next
    Kill strFilePath
    On Error GoTo 0
    

    第三个是内联代码,仅当文件恰好存在时才采取行动:

    On Error Resume Next
    GetAttr strFilePath
    If Err Then
        On Error GoTo 0
        ProcessTheData strFilePath
    End If
    On Error GoTo 0
    

    虽然对于初学者来说可能看起来很尴尬(在两个地方执行 On Error GoTo 0),但与来回跳转以处理各种异常的大量 On Error GoTo Label 相比,结果不那么笨拙且更有条理。

    好处是您还可以移植到 VBScript,因为 On Error GoTo Label 根本不是一个有效的构造。

    【讨论】:

      【解决方案4】:

      On Error GoTo 0 禁用当前过程中任何已启用的错误处理程序并清除Err 对象,该对象不会通过退出发生错误的过程来清除。您通常直接在可能导致错误的语句之后插入此语句。

      例子:

      Function ShowError() As String
        Dim i As Long
        ShowError = "No error occurred!"
        On Error Resume Next
        ActiveDocument.Styles("codechar1").LanguageID = wdEnglishUS
        If (Not (Err Is Nothing)) Then ShowError = Err.Description 
        'On Error GoTo 0
      End Function
      
      Sub ApplyShowError()
        MsgBox ShowError & vbNewLine & Err.Description
       End Sub
      

      现在假设ActiveDocument 对象不包含名为codechar1 的样式。然后发生错误,函数ShowError 返回“请求的集合成员不存在”。如果On Error GoTo 0这一行被注释掉了,Err对象并没有被清除并且在函数ShowError的退出中仍然存在,所以调用过程再次输出这个错误信息。

      【讨论】:

        【解决方案5】:

        此链接可能对您有所帮助:http://answers.microsoft.com/en-us/office/forum/office_2010-excel/why-on-error-resume-next-and-on-error-goto-0-have/a110548f-95c9-44ac-89bc-19697641804a?auth=1

        基本上它解释了 On Error Resume Next 告诉 VB 跳过发现的任何错误并转到代码中的下一个过程或行,而 On Error GoTo 0 恢复默认错误处理。

        【讨论】:

          猜你喜欢
          • 2012-12-18
          • 1970-01-01
          • 1970-01-01
          • 2013-03-10
          • 1970-01-01
          • 2015-05-15
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多