Recipe7.4.Handling Derived Exceptions Individually


Recipe 7.4. Handling Derived Exceptions Individually

Problem

You have an exception hierarchy that consists of a base exception class and multiple derived exception classes. At some point in your code, you want to handle only one or two of these derived exceptions in a specific manner. All other derived exceptions should be handled in a more generic manner. You need a clean way to indicate that certain exceptions in an exception class hierarchy should be handled differently from the rest.

Solution

The exception handlers for C# allow for multiple catch clauses to be implemented. Each of these catch clauses can take a single parametera type derived from the Exception class. An exception handler that uses multiple catch clauses is shown here:

 try {     int d = 0;     int z = 1/d; } catch(DivideByZeroException dbze) {     Console.WriteLine("A divide by zero exception occurred. Error message == "       + dbze.Message); } catch(OverflowException ofe) {     Console.WriteLine("An Overflow occurred. Error message == " + ofe.Message); } catch(Exception e) {     Console.WriteLine("Another type of error occurred. Error message == "       + e.Message); } 

This code produces the following output:

 A divide by zero exception occurred. Error message == Attempted to divide by zero. 

Discussion

Notice the exception types that each catch clause handles in this TRy-catch block. These specific exception types will be handled on an individual basis within their own catch block. Suppose the try block looks like this:

 try {     int z2 = 9999999;     checked{z2 *= 999999999;} } 

You will get the following message:

 An Overflow occurred. Error message == Arithmetic operation resulted in an overflow. 

Now, since the OverflowException is being thrown, it is handled in a totally different catch block.

You could do the same thing in a single catch block using an if-else statement. An example of this is shown here:

 catch(Exception e) {     if (e is OverflowException)         Console.WriteLine("An Overflow occurred. Error message == " + e.Message);     else if (e is DivideByZeroException)         Console.WriteLine("A divide by zero exception occurred. Error message == " +                            e.Message);     else         Console.WriteLine("Another type of error occurred. Error message == " +                            e.Message); } 

The if-else statements are used to check the type of this exception and then execute the appropriate code. This structure has two flaws. The first is that the compiler does not check whether the exceptions are listed in the correct order in the if-else statements. If a derived exception class is placed in the if-else conditional structure after the exception class that it inherits from (Arthimetic Exception), then the derived exception class will never be checked. Consider the following modified catch clause:

 try {     int d = 0;     int z = 1/d; } catch(Exception e) {     if (e is ArithmeticException)         Console.WriteLine("The base class exception was chosen.");     else if (e is OverflowException)         Console.WriteLine("An Overflow occurred. Error message == " + e.Message);     else if (e is DivideByZeroException)         Console.WriteLine("A divide by zero exception occurred. Error message == " +                            e.Message);     else         Console.WriteLine("Another type of error occurred. Error message == " +                            e.Message); } 

This code produces the following output:

 The base class exception was chosen. 

Even though the DivideByZeroException was thrown, the ArithmeticException is always found first, as the DivideByZeroException and OverflowException both have the ArithmeticException class as their base class.

The second flaw is one of appearance. Using multiple catch clauses is much easier to read thanks to its natural and consistent structure. This is the way the language should be used, and, therefore, this is what many developers are going to look for.

Other developers reading your code may find it more natural to read the multiple catch classes rather than the single catch clause with a decision structure inside of it. There is one case in which you might consider using the single catch clause with the decision structure: when large amounts of code would have to be duplicated in each catch clause and there is no way to put the duplicated code in a finally clause after the TRy-catch block. Even this scenario offers the alternative of structuring the code in a nested TRy-catch fashion like this:

 try {     try     {         …code here…     }     catch     {         …put the code that is common to handling all exceptions here throw;     } } catch (ExceptionTypeA a) {     … do specific exception A handling here } catch (ExceptionTypeB b) {     … do specific exception B handling here } 

See Also

See the "Error Raising and Handling Guidelines" topic in the MSDN documentation.



C# Cookbook
Secure Programming Cookbook for C and C++: Recipes for Cryptography, Authentication, Input Validation & More
ISBN: 0596003943
EAN: 2147483647
Year: 2004
Pages: 424

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