Microsoft has added structured exception handling to Visual Basic, and as you might expect, it's now considered the recommended method of exception handling. In fact, it is appropriate to call the On Error GoTo method of exception handling unstructured, because using this statement just sets the internal exception handler in Visual Basic; it certainly doesn't add any structure to your code, and if your code extends over procedures and blocks, it can be hard to figure out what exception handler is working when.
Structured exception handling is based on a particular statement, the Try…Catch…Finally statement, which is divided into a Try block, optional Catch blocks, and an optional Finally block. The Try block contains code where exceptions can occur, the Catch block contains code to handle the exceptions that occur. If an exception occurs in the Try block, the code throws the exception—actually an object based on the Visual Basic Exception class—so it can be caught and handled by the appropriate Catch statement. After the rest of the statement finishes, execution is always passed to the Finally block, if there is one. Here's what the Try…Catch…Finally statement looks like in general:
Try
[ tryStatements ]
[Catch [ exception1 [ As type1 ] ] [ When expression1 ]
catchStatements1
[Exit Try] ]
[Catch [ exception2 [ As type2 ] ] [When expression2 ]
catchStatements2
[ Exit Try ] ]
⋮
[Catch [ exceptionn [ As typen ] ] [ When expressionn ]
catchStatementsn ]
[ Exit Try ] ]
[ Finally
[ finallyStatements ]
End Try
Here are the parts of this statement:
Try—Begins the Try block for structured exception handling.
tryStatements—Sensitive statements where you expect exceptions.
Catch—If an exception happens in the Try block, the exception is thrown and each Catch statement is examined in order to determine if it will handle the exception.
exception—A variable name you give the exception. The value of exception is the value of the thrown exception.
type—Specifies the type of the exception you're catching in a Catch statement.
When—A Catch clause with a When clause will only catch exceptions when expression evaluates to True.
expression—An expression used to select exceptions to handle; must be convertible to a Boolean value. Often used to filter exceptions by number.
catchStatements—Statements to handle exceptions occurring in the Try block.
Exit Try—Statement that breaks out of the Try…Catch…Finally structure. Execution is transferred to the code immediately following the End Try statement. Note that Exit Try is not allowed in Finally blocks.
Finally—A Finally block is always executed when execution leaves any part of the Try statement.
finallyStatements—Statements that are executed after all other exception processing has occurred.
Note |
If a Try statement does not contain any Catch blocks, it must contain a Finally block. |
Tip |
Bear in mind that if exceptions occur that the code does not specifically handle, Visual Basic will default to its normal exception message. |
If you supply the optional Finally statement, the corresponding statement block is always the last code to be executed just before control leaves Try…Catch…Finally. This is true even if an unhandled exception occurs, or if you execute an Exit Try statement. And note that you can have any number of Catch statements (however, you must have at least one Catch statement or a Finally statement).
Here's an example; in this case, the exception-prone code executes a division by zero, which generates an arithmetic overflow exception. Note that I place the sensitive code in the Try block, and the exception-handling code in the Catch block:
Module Module1 Sub Main() Dim int1 = 0, int2 = 1, int3 As Integer Try int3 = int2 / int1 System.Console.WriteLine("The answer is {0}", int3) Catch System.Console.WriteLine("Exception: Arithmetic overflow!") End Try End Sub End Module
When you run this console application, you'll see:
Exception: Arithmetic overflow!
You also can get more information about the exception by getting an exception object; I'll do that here by catching any exception based on the Exception class—which means all exceptions—and using the exception object's ToString method to display information about the exception:
Module Module1 Sub Main() Dim int1 = 0, int2 = 1, int3 As Integer Try int3 = int2 / int1 System.Console.WriteLine("The answer is {0}", int3) Catch e As Exception System.Console.WriteLine(e.ToString) End Try End Sub End Module
Here's what you see when you run this code:
System.OverflowException: Exception of type System.OverflowException was thrown. at Microsoft.VisualBasic.Helpers.IntegerType.FromObject(Object Value) at ConsoleApp.Module1.Main() in C:\vbnet\ConsoleApp\Module1.vb:line 5
This kind of information is more useful to the programmer than to the user. For the user, you might display the message in the exception object's message property (that is, use e.message instead), which gives you this:
Exception of type System.OverflowException was thrown.
That's a little better, but of course, it's best to catch individual exceptions yourself and to customize the messages you display to your application. Take a look at the next topic for the details.