Introduction
There are a very large number of new things in Visual FoxPro 8.0. Many more than could ever be covered in a single article. In this article I will introduce you to new way of handling errors and/or exceptions in Visual FoxPro 8.0.
Structured error handling
In my opinion one of the most valuable additions to the VFP language in version 8.0 is the introduction of structured error handling. How often have you coded something like the example below?
** Example 1: Local error handling **
* Some program where we need to open a table exclusively
LOCAL lcError
lcError = ON(“Error”)
ON ERROR lnError = ERROR()
IF USED(“MYTable”)
USE IN MyTable
ENDIF
SELECT 0
USE MyTable EXCLUSIVE
IF NOT EMPTY(lcError)
ON ERROR &lcError
ENDIF
IF lnError = 108 && File is in use …
RETURN .F.
ENDIF
* Do the rest of the file stuff here
The code above is intended to attempt to open a table (MyTable) exclusively. It goes through a bunch of stuff to trap the situation where the file is open and in use by some other user.
One of the most valuable additions to the VFP language in version 8.0 is the introduction of structured error handling
Structured error handling addresses this very situation in a simple and most elegant way. Below is the same functionality using the structured error handling.
** Example 2: Stucturesd error handling **
* Begin the error handling block
TRY
* Set return value
llRet = .T.
* Attempt to open the table exclusively
USE MyTable EXCLUSIVE
INDEX ON Field1 TAG Field1
USE
CATCH TO oErr
* Error has occured
?[ Error: ] + STR(oErr.ErrorNo)
?[ LineNo: ] + STR(oErr.LineNo)
?[ Message: ] + oErr.Message
* Set return value
llRet = .F.
* End of error block
ENDTRY
RETURN llRet
In the above example the TRY command begins a Try-Catch construct. The code following the TRY statement is executed in the normal fashion. If there are no errors, then the Try section’s code is run and when VFP encounters the CATCH command the execution jumps ahead to the ENDTRY command (or to the FINALLY statement if one exists).
If any error occurs in the Try code, execution is immediately transferred to the Catch line. The CATCH TO oErr causes an exception object to be created and populated with information about the error that occurred. You can see in the code following the Catch statement that the exception object has properties that hold information about the situation.
The exception object has properties that hold information about the situation
There is additional functionality available in the Try-Catch construct. There can be more than one Catch statement. When using multiple Catches you can use the WHEN clause to control which Catch code is executed based on some logical expression. For example, we could change the above code to the following.
** Example 3: More catches **
* Structured Error Handling
* Begin the error handling block
TRY
* Set return value
llRet = .T.
* Attempt to open the table exclusively
USE MyTable EXCLUSIVE
INDEX ON Field1 TAG Field1
USE
CATCH TO oErr WHEN ERROR() = 108
* A file is in use error has occurred
?[ Error: ] + STR(oErr.ErrorNo)
?[ LineNo: ] + STR(oErr.LineNo)
?[ Message: ] + oErr.Message
* Set return value
llRet = .F.
CATCH TO oErr
* Some other error has occurred
?[ Error: ] + STR(oErr.ErrorNo)
?[ LineNo: ] + STR(oErr.LineNo)
?[ Message: ] + oErr.Message
* Set return value
llRet = .F.
* End of error block
ENDTRY
RETURN llRet
There is more to the Try-Catch construct, like a FINALLY clause which is executed after the catch code finishes. There is also a THROW command that you use to promote the error condition up to a higher Try-Catch construct when there are nested Try-Catches.
When you get your copy of VFP 8, be sure to read the help file about this new, well new to VFP, approach to error handling.
So what’s so great about this?
There are a number of advantages to be realized by leveraging the Try-Catch approach to error handling. The major one, to me, is that you can keep the error handling right in the actual code that may incur the error. This makes for clearer handling of exceptions.
Summary
In VFP 8 we can try something, if needed we can catch any problems, then finally finish our activities. If we happen to be coding some actions that reside inside of another Try-Catch we can throw the problem to Try-Catch in which our code resides. All of that and we can pass the problem around inside of an error object.
Jim Booth