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 th开发者_如何学JAVAe 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:
- VBA Error "Bubble Up"
- Handling errors in math functions
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
Exit Sub will exit the subroutine immediatly like return in Java
End Sub is just the marker for the end of the sub routine block like } in Java
A label is simply a mark in the code wich is used to define a jump destination. In case you did not jump to the label but arrived there "regularly" the label itself will be ignored but the code after the label will be executed as if there was no label, the code in your example will be executed all the way to the Exit Sub statement as long as no error occurs. If one occures it will jump to ProcError
Resume will in this case execute ProcExit see more here
精彩评论