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.
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.
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.