VB Exceptions

Exceptions are relatively new to VB; therefore, many VB programmers will take a little while to get used to the syntax and the idea behind exceptions. VB's On Error GoTo XXX resembles current exception handling.

Basic VB Exceptions

Listings 15.15 and 15.16 illustrate the basics of VB exception handling. This code sample follows the form of the VC++ sample shown earlier in that an ExceptionGenerator throws or causes various exceptions based on an integer selector that is passed as an argument. This sample illustrates a custom exception, a divide-by-zero exception, a stack overflow exception, and a FileNotFoundException. The full source for this sample can be found in the VBExceptionsBasicExceptions directory. Listing 15.15 shows the essential parts of generating and catching a custom exception.

Listing 15.15. VB Custom Exception
'Create a custom exception type called MyException. What makes
' it an exception is that it inherits from System.ApplicationException
Public Class MyException
    Inherits System.ApplicationException

    'Define the three standard constructors for an ApplicationException
    Public Sub New()
        MyBase.New()
    End Sub

    Public Sub New(ByVal Message As String)
        MyBase.New(Message)
    End Sub

    Public Sub New(ByVal Message As String, ByVal Inner As Exception)
        MyBase.New(Message, Inner)
    End Sub

End Class
. . .
    Sub ThrowMyException()
        Throw New MyException("This exception is thrown from ThrowMyException")
    End Sub
. . .
Case 0
    ' Custom Exception
    ThrowMyException()

The first section of this code shows how a custom exception class is defined. First, notice that it is derived from ApplicationException. Second, most of the code is defining constructors to handle various types of construction. No new functionality is added to ApplicationException, yet it is still a valid custom exception. VB is like C# in that it does not support an exception class that is not at least derived from System.Exception. If you try to use a custom exception that is not derived from System.Exception, the compiler will issue an error:

The argument to Throw must derive from System.Exception.

The next section of code shows the exception class being constructed and thrown. Here, the second constructor (New(ByVal Message As String)) is being used to build the exception class.

Finally, the case in the Select statement that calls the function is illustrated. Catching the exception that is thrown is common to all of the exceptions in this sample; this is shown more explicitly in Listing 15.16 if you want to look ahead.

The next exceptions are so similar to exceptions that are already illustrated that this chapter will cover them quickly. To generate a DivideByZeroException, the following code is used:

Case 1
    ' DivideByZero
    a = 0
    b = 1
    c = b  a

To generate a StackOverflowException, initiate an infinite recursion, repeatedly calling itself until the stack overflows:

Case 2
    ' StackOverflow
    ExceptionGenerator(2)

To test a FileNotFoundException, the exception is thrown directly. The FileStream class in the System.IO namespace would typically throw the FileNotFoundException. Here you are concerned only with the exception, so it is thrown directly.

Case 3
    ' Overflow
    Throw New FileNotFoundException("Testing")

Each of these exceptions is handled in the same way as shown in Listing 15.16.

Listing 15.16. Catching VB Exceptions
Sub Main()
    Dim i As Integer
    For i = 0 To 3 Step 1
        Try
            ExceptionGenerator(i)
        Catch e As Exception
            Console.WriteLine("Exception Caught")
            Console.WriteLine(e.ToString())
        Finally
            Console.WriteLine()
        End Try
    Next
End Sub

The output from this sample is much the same as the C# or C++ code samples. The ToString() method of an exception creates a string that includes the name of the exception, a customizable message, and a stack trace.

Advanced VB Exceptions

In the sample shown in Listing 15.16, when an SEH exception is caught, the argument to __except is an expression or a function that evaluates to one of three values that determines whether the exception can be handled with the current __except block. If multiple __except blocks were in the sample and EvalException returned EXCEPTION_CONTINUE_SEARCH, the next __except block would be evaluated to see if it was a candidate to handle the exception. This process would continue until all of the __except blocks had been searched. If none of the __except blocks accepted the exception, then the exception would be considered unhandled.

VB exposes a feature that is similar to SEH with the When clause of the Catch statement. The statement associated with the When clause must evaluate to a Boolean true or false. If the When clause evaluates to false, then the next Catch block is evaluated, and so on. Listing 15.17 shows a sample that illustrates this feature. The complete code for this sample is in the directory VBExceptionsAdvancedExceptions.

Listing 15.17. Filtering VB Exceptions
Dim i As Integer
For i = 0 To 1 Step 1
    Try
        Throw New MyException("This exception is thrown from Main")
    Catch e As MyException When i = 0
        Console.WriteLine("MyException Caught")
        Console.WriteLine(e.ToString())
    Catch e As Exception
        Console.WriteLine("Exception Caught")
        Console.WriteLine(e.ToString())
    Finally
        Console.WriteLine()
    End Try
Next

As can be seen from the code, the set of Try/Catch blocks is executed twice. The first time when the index variable i is 0, MyException is caught. The second time around, the index variable i is no longer zero, so the When clause is false and the search for a suitable exception handler continues to the next block. Because MyException is derived from ApplicationException, which ultimately derives from Exception, the next block is also of the correct type, and the second time around, the exception is caught in this block. The output from this sample looks like this:

MyException Caught
AdvancedExceptions.MyException: This exception is thrown from Main
   at AdvancedExceptions.AdvancedExceptions.Main() in AdvancedExceptions.vb: line 9
Exception Caught
AdvancedExceptions.MyException: This exception is thrown from Main
   at AdvancedExceptions.AdvancedExceptions.Main() in AdvancedExceptions.vb: line 9

Because of the When clause, each of the available exception handlers handle the same exception.

To illustrate another feature of VB exception handling, Listing 15.18 shows how the same functionality as shown in Listing 15.17 can be achieved with a non-local goto. The source to this listing is also a part of the sample code in VBExceptionsAdvancedExceptions.

Listing 15.18. VB Exceptions Filtering and goto
        i = 0
        Try
retry:
            Throw New MyException("This exception is thrown from Main")
        Catch e As MyException When i = 0
            Console.WriteLine("MyException Caught")
            Console.WriteLine(e.ToString())
            i = i + 1
            Goto retry
        Catch e As Exception
            Console.WriteLine("Exception Caught")
            Console.WriteLine(e.ToString())
        Finally
            Console.WriteLine()
        End Try

On entering the try block the first time, the variable i is 0; therefore, like the sample in Listing 15.17, MyException is caught in the first catch block. After printing information about the exception that is caught, i is incremented and execution is transferred back up to the try block via the goto statement. This is not supported or legal in C#. Trying to do this will result in a compiler error:

No such label 'retry' within the scope of the goto statement

In other words, any non-local goto is blocked in C#—not just in try/catch blocks; therefore, VB offers at least two features that are not exposed with C# when it comes to handling exceptions. Another rule that is enforced with C# is that you cannot leave the body of a finally clause. In other words, you cannot use goto or return, which cause the execution path to leave a finally clause. Because C# limits the scope of a label, it is not possible to jump into a try block.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.188.142.146