Recipe 5.5 Assuring Exceptions are Not Lost when Using Finally Blocks

Recipe 5.5 Assuring Exceptions are Not Lost when Using Finally Blocks

Problem

You have multiple nested try / catch , try / finally , and try / catch / finally blocks. If a catch block attempts to rethrow an exception, it is possible that the rethrown exception could get discarded and a new and unexpected exception could be caught by an outer exception handler. You want to prevent this situation from occurring.

Solution

Add an inner try / catch block in the finally block of the outer exception handler:

 private void PreventLossOfException( ) {     try     {         //...       }     catch(Exception e)     {         Console.WriteLine("Error message == " + e.Message);         throw;     }     finally     {  try   {   //..  .  }   catch(Exception e)   {   Console.WriteLine(@"An unexpected error occurred in the finally block  .  Error message == " + e.Message);   }  } } 

This block will prevent the original exception from being lost.

Discussion

Consider what would happen if an error were thrown from the inner finally block contained in the ReThrowException method. If the code looked like this:

 public void PreventLossOfException( ) {     try     {         Console.WriteLine("In outer try");         ReThrowException( );     }     catch(Exception e)     {         Console.WriteLine("In outer catch.   ReThrown error == " + e.Message);     }     finally     {         Console.WriteLine("In outer finally");     } } private void ReThrowException( ) {     try     {         Console.WriteLine("In inner try");         int z2 = 9999999;         checked{z2 *= 999999999;}       }     catch(OverflowException ofe)     {         Console.WriteLine("An Overflow occurred.   Error message == " +                             ofe.Message);         throw;     }     catch(Exception e)     {         Console.WriteLine("Another type of error occurred.   Error message == " +                             e.Message);         throw;     }     finally     {         Console.WriteLine("In inner finally");         throw(new Exception("Oops"));        } } 

the following output would be displayed:

 In outer try In inner try An Overflow occurred.   Error message == Arithmetic operation resulted in an overflow. In inner finally In outer catch.   ReThrown error == Oops In outer finally 

If we modify the inner finally block to handle its own errors (changes are highlighted), similar to the following code:

 public void PreventLossOfException( ) {     try     {         Console.WriteLine("In outer try");         ReThrowException( );     }     catch(Exception e)     {         Console.WriteLine("In outer catch.   ReThrown error == " + e.Message);     }     finally     {         Console.WriteLine("In outer finally");     } } private void ReThrowException( ) {     try     {         Console.WriteLine("In inner try");         int z2 = 9999999;         checked{z2 *= 999999999;}       }     catch(OverflowException ofe)     {         Console.WriteLine("An Overflow occurred.   Error message == " +                            ofe.Message);         throw;     }     catch(Exception e)     {         Console.WriteLine("Another type of error occurred.   " +                           "Error message == " + e.Message);         throw;     }     finally     {  try   {   Console.WriteLine("In inner finally");   throw(new Exception("Oops"));   }   catch(Exception e)   {   Console.WriteLine(@"An error occurred in the finally block. " +  "  Error message == " + e.Message);   }  } } 

we would get the following output:

 In outer try In inner try An Overflow occurred.   Error message == Arithmetic operation resulted in an overflow. In inner finally An error occurred in the finally block.   Error message == Oops In outer catch.   ReThrown error == Arithmetic operation resulted in an overflow. In outer finally 

By handling exceptions within the inner finally block, we assure that the correct re-thrown exception bubbles up to the next outer exception handler.

When writing a finally block, consider placing a separate try-catch around the code.


See Also

See the "Error Raising and Handling Guidelines" topic and the "throw," "try," "catch," and "finally" keywords in the MSDN documentation.



C# Cookbook
C# 3.0 Cookbook
ISBN: 059651610X
EAN: 2147483647
Year: 2003
Pages: 315

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