GOTCHA 13 Ordering of catch processing isn t consist across languages


GOTCHA #13 Ordering of catch processing isn't consist across languages

A language should avoid surprises as much as possible. Its behavior should be intuitive, consistent, and predictable. Unfortunately, both C# and VB.NET have some odd quirks. In this gotcha, I'll pick on VB.NET.

For instance, suppose you have a hierarchy of exceptions, say Exception E2 inherits from E1, which in turn inherits from System.ApplicationException. When you place catch blocks in your code, what order should you put them in? Should you write the catch for E2 before the one for E1? Or code the catch for E1 before the catch for E2?

The C# compiler tries to help by giving you a compilation error if you place them in the wrong order. However, in VB.NET, you are in for a surprise. Consider Example 2-5.

Example 2-5. Order of catch

C# (CatchOrder)

 using System; namespace OrderOfCatch {     class Program     {         public static void AMethod()         {             throw new ApplicationException();         }         [STAThread]         static void Main(string[] args)         {             try             {                 AMethod();             }              catch(Exception ex)             {                 Console.WriteLine("Caught Exception");             }              catch(ApplicationException ae)                 // Results in compilation error.             {                 Console.WriteLine(                     "Caught ApplicationException");             }         }     } } 

VB.NET (CatchOrder)

 Module Program     Public Sub AMethod()         Throw New ApplicationException     End Sub     Sub Main(ByVal args As String())         Try             AMethod()          Catch ex As Exception             Console.WriteLine("Caught Exception")          Catch ae As ApplicationException             Console.WriteLine("Caught ApplicationException")         End Try     End Sub End Module 

C# generates the following compilation error:

    error CS0160: A previous catch clause already catches all exceptions of this or a    super type ('System.Exception'). 

However, VB.NET does not report an error (it does not even report a warning). Executing the VB.NET version of the code produces the output in Figure 2-5.

Figure 2-5. Output from VB.NET version of Example 2-5


Instead of the catch block for System.ApplicationException being called, you end up in the catch for System.Exception.

Now let's reverse the order of the catch blocks as shown in Example 2-6.

Example 2-6. Reversing the order of catch

VB.NET (CatchOrder)

 Module Program     Public Sub AMethod()         Throw New ApplicationException     End Sub     Sub Main(ByVal args As String())         Try             AMethod()          Catch ae As ApplicationException             Console.WriteLine("Caught ApplicationException")          Catch ex As Exception             Console.WriteLine("Caught Exception")         End Try     End Sub End Module 

The program now produces the desired output, as shown in Figure 2-6.

Figure 2-6. Output for code in Example 2-6


When writing VB.NET code, you have to pay attention to the order of your catch blocks. The runtime is going to find the first matching type for a catch. If the base type appears before the derived type, even though a more specific type appears later in the catch sequence, the base type will handle the exception. This is why you see the difference in output between the two VB.NET code versions above.

You can use the .NET Reflector tool (see the section "On the Web" in the Appendix) to find the relationship between classes by examining the Base Types and Derived Types nodes, as shown in Figure 2-7.

Figure 2-7. Reflector showing class hierarchy


How does this differ in .NET 2.0 Beta 1? For the VB.NET code, the compiler gives a warning (though still not an error):

    warning BC42029: Catch block never reached, because 'System.ApplicationException'    inherits from 'System.Exception'. 

IN A NUTSHELL

In VB.NET, if you write multiple catch statements, make sure you place them in the proper order, with catch handlers for derived exception types appearing before the catch handlers for their base types.

SEE ALSO

Gotcha #15, "rethrow isn't consistent" and Gotcha #26, "Details of exception may be hidden."



    .NET Gotachas
    .NET Gotachas
    ISBN: N/A
    EAN: N/A
    Year: 2005
    Pages: 126

    flylib.com © 2008-2017.
    If you may any questions please contact us: flylib@qtcs.net