我们需要为每个子例程创建一个错误处理程序吗?

时间:2011-05-27 07:42:08

标签: vba error-handling program-flow

我从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:之类的标签时,是执行它还是跳过它?

2 个答案:

答案 0 :(得分:9)

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

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

更多信息,请参阅@jtolle的两个优秀答案:

此外,互联网搜索将揭示网上有关于错误处理的整个文献。在我看来,有些是非常错误的!但如果它坚持我在前两段写的内容,那么值得考虑。

Exit SubEnd Sub非常直观:前者停止执行当前Sub并将控制权返回给调用它的过程(如果另一个过程没有调用过程,则完全停止执行) 。后者只是对编译器的指示,即此特定Sub的代码结束 - 如果执行,End Sub的行为类似于Exit Sub

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

如果在执行过程中遇到诸如ProcError:之类的标签,则不会发生任何特殊情况,执行将转移到标签后的下一个语句。当然在你的例子中,ProcError:永远不会直接执行(即除非出现错误),因为它前面有一个Exit Sub


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

ProcExit:

答案 1 :(得分:2)

Exit Sub将立即退出子程序,如Java中的return

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

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

在这种情况下,恢复将执行ProcExit,请参阅更多here