【问题标题】:Do we need to create a error handler for each subroutine?我们是否需要为每个子例程创建一个错误处理程序?
【发布时间】:2011-09-03 04:55:00
【问题描述】:

我从 SO 中复制一段代码作为示例。该子例程包含一个错误处理程序。是否应该为所有 Subs 创建一个错误处理程序?

Public Sub SubA()
  On Error Goto ProcError

  Connection.Open
  Open File for Writing
  SomePreciousResource.GrabIt

ProcExit:  
  Connection.Close
  Connection = Nothing
  Close File
  SomePreciousResource.Release

  Exit Sub

ProcError:  
  MsgBox Err.Description  
  Resume ProcExit
End Sub

顺便问一下,当代码执行器遇到Exit SubEnd SubResume时,子程序内部的控制流程如何?而当它在执行过程中遇到ProcError:等标签时,是执行还是跳过?

【问题讨论】:

    标签: vba error-handling program-flow


    【解决方案1】:

    Exit Sub 会像 Java 中的 return 一样立即退出子程序

    End Sub 只是子例程块结束的标记,如 Java 中的 }

    标签只是代码中的一个标记,用于定义跳转目标。如果您没有跳转到标签但“定期”到达那里,标签本身将被忽略,但标签后面的代码将被执行,就好像没有标签一样,您示例中的代码将一直执行到只要不出错就退出 Sub 语句。如果发生了它会跳转到 ProcError

    在这种情况下,Resume 将执行 ProcExit 查看更多here

    【讨论】:

    • 你说标签块会被忽略,但它如何识别块并与其余代码分开?
    • @gunbuster363:我认为@cmmi 的说法是正确的,虽然表达得不是很清楚。 “标签将被忽略”的意思是:标签本身在执行时不做任何事情。但是,标签后面的代码(你称之为“标签块”)肯定不会被忽略,会被执行。
    【解决方案2】:

    简短的回答是:不,您不仅需要在每个过程中都有一个错误处理程序,而且实际上您通常也不想要一个错误处理程序在每个程序中。

    您将希望在最有意义的地方进行错误处理。通常,您只想在最高级别的过程中使用错误处理程序,即调用所有其他程序的错误处理程序;较低级别的程序应该将问题踢到楼上,并让错误“冒泡”到较高级别的程序。有时您会希望在较低级别的过程中进行一些错误处理。

    有关更多信息,我建议您参考@jtolle 的这两个出色的答案:

    此外,通过 Internet 搜索会发现网络上有大量关于错误处理的文献。在我看来,其中一些是完全错误的!但如果它坚持我在前两段中写的内容,那么值得考虑。

    Exit SubEnd Sub 相当直观:前者停止当前 Sub 的执行并将控制权返回给调用它的过程(或者如果该过程未被另一个过程调用,则完全停止执行)。后者只是向编译器表明此特定 Sub 的代码在此结束 - 如果执行,End Sub 的行为类似于Exit Sub

    Resume 指定在错误处理例程完成后接下来应该发生什么。 Plain Resume 返回导致错误的同一语句并尝试再次执行它。 Resume Next 跳过导致错误的语句,而是转到紧随其后的语句。 Resume mylabel 转到标签 mylabel:

    如果在执行过程中遇到了诸如ProcError: 之类的标签,则不会发生任何特殊情况,并且会继续执行标签之后的下一条语句。当然,在您的示例中,ProcError: 永远不会直接执行(即除非引发错误,否则不会直接执行),因为在它之前有一个 Exit Sub


    顺便说一句,ProcExit: 块应该以On Error Resume Next 开头(即继续关闭所有内容并退出,无论任何错误),或者正如@Phydaux 指出的那样,On Error Goto 0(错误, 停止执行),否则如果其中的某些内容触发错误,您可能会进入错误处理程序和ProcExit: 代码之间的无限乒乓循环。

    ProcExit:
       On Error Resume Next ' or, alternatively, On Error Goto 0
       Connection.Close
       Connection = Nothing
       Close File
       SomePreciousResource.Release
    Exit Sub
    

    【讨论】:

    • @Jean:为错误处理程序标签后的On Error Resume Next +1。让我重新思考我在做什么。但是,如果我想在发生错误之后的行被执行怎么办?在这种情况下使用Resume Next 可以吗?希望你明白我想说的(英语不是我的母语)。
    • 对于 ProcExit: 部分,On Error GoTo 0 也可能是合适的。但您肯定想要其中之一,否则您将面临无限循环的风险。
    • @Oneide:你的意思是,做错误处理,然后继续执行导致错误的语句后面的那行?是的,在这种情况下,Resume Next 应该是错误处理程序的最后一条语句。不过,老实说,我从来没有真正找到这样做的充分理由。
    • @Jean:非常感谢。我稍后会做一些测试,但我认为现在已经很清楚了。
    • @Phydaux:好点(再次)。编辑答案以突出显示这一点。
    猜你喜欢
    • 1970-01-01
    • 2021-11-02
    • 1970-01-01
    • 2021-11-03
    • 2016-06-26
    • 1970-01-01
    • 2012-11-14
    • 2016-09-25
    • 1970-01-01
    相关资源
    最近更新 更多