我们需要为每个子例程创建一个错误处理程序吗? [英] Do we need to create a error handler for each subroutine?

查看:132
本文介绍了我们需要为每个子例程创建一个错误处理程序吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

例如,我从SO中复制一段代码。子程序包含一个错误处理程序。应该为所有的Subs做一个错误处理程序?

  Public Sub SubA()
错误Goto ProcError

Connection.Open
打开文件写入
SomePreciousResource.GrabIt

ProcExit:
Connection.Close
Connection = Nothing
关闭文件
SomePreciousResource.Release

退出子

ProcError:
MsgBox Err.Description
恢复ProcExit
结束子

顺便说一下,当代码执行者遇到一个子例程时,控件的流程如何退出子 End Sub 简历?而在执行期间遇到诸如 ProcError:的标签,是否执行它,否则会跳过?

解决方案

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



您将需要做出最有意义的错误处理。通常,您只需要最高级别的过程中的错误处理程序,即调用所有其他过程的错误处理程序。较低级别的程序应该把楼上的问题踢出来,让错误冒泡到更高层次的程序。有时你会想要在较低级别的程序中进行一些错误处理。



对于更多,我引用你这两个很好的答案@jtolle:





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



退出子 End Sub 相当直观:前者停止执行当前的Sub,并将控制权返回给调用它的过程(或如果该过程未被其他过程调用,则完全停止执行)。后者只是指示编译器,这个特定子代码的代码结束,如果执行的话,$ code> End Sub 的行为就像 Exit Sub



恢复指定错误处理例程完成后应该发生什么。平原恢复返回到导致错误的同一语句,并尝试再次执行。 继续下一步跳过导致错误的语句,而是转到紧跟其后的语句。 恢复mylabel 转到标签 mylabel:



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






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

  ProcExit:
On Error Resume Next或者替代为On错误Goto 0
Connection.Close
Connection = Nothing
关闭文件
SomePreciousResource.Release
退出子


I copy a piece of code from SO as an example. The subroutine contains an error handler. Should one make an error handler for all 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

And by the way, how does the flow of the control inside a subroutine when the code executor encounter a Exit Sub, End Sub and Resume? And when it encounters a label such as ProcError: during the execution, does it execute it, or does it skip it?

解决方案

The short answer is: No, not only do you not need to have an error handler in each procedure, but in fact you would usually not want an error handler in each procedure.

You will want to do the error handling where it makes most sense to do it. Often, you would only want an error handler in the highest-level procedure, i.e. the one that calls all the others; lower-level procedures should kick the problem upstairs and let errors "bubble up" to the higher-level procedure. Sometimes you will want some error handling in lower-level procedures.

For more, I refer you to these two excellent answers by @jtolle:

Also, an internet search will reveal that there is a whole literature on the web about error handling. Some of it is quite wrong, in my opinion! But if it sticks to what I wrote in the first two paragraphs, then it's worth considering.

Exit Sub and End Sub are fairly intuitive: the former stops execution of the current Sub and returns control to the procedure that called it (or stops execution entirely if the procedure was not called by another procedure). The latter is just a indication to the compiler that this where the code for this particular Sub ends -- and if executed, End Sub behaves like Exit Sub.

Resume specifies what should happen next, after an error-handling routine is finished. Plain Resume returns to the same statement that caused the error and tries to execute it again. Resume Next skips the statement that caused the error, and instead goes to the statement immediately following it. Resume mylabel goes to label mylabel:.

If a label such as your ProcError: is encoutered in the course of execution, then nothing special happens, and execution moves on to the next statement after the label. Of course in your example, ProcError: will never get executed directly (i.e. not unless an error is raised) because there's an Exit Sub just before it.


By the way, the ProcExit: block should probably start with an On Error Resume Next (i.e. keep on closing everything and exiting regardless of any errors) or alternatively, as pointed out by @Phydaux, an On Error Goto 0 (on error, stop execution), otherwise if something in there triggers an error, you may get into an infinite ping-pong loop between the error handler and the ProcExit: code.

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

这篇关于我们需要为每个子例程创建一个错误处理程序吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆