5

我从 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 Sub,End Sub和时,子程序内部的控制流程如何Resume?而当它遇到诸如ProcError:执行过程中的标签时,它是执行它,还是跳过它?

4

2 回答 2

10

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

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

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

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

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

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

如果在执行过程中遇到了诸如 your 之类的标签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
于 2011-05-27T08:25:17.073 回答
2

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

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

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

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

于 2011-05-27T07:49:48.323 回答