The finally Block

   


The finally Block

Consider a method that opens a file in its first statements and closes the file just before the method exits. If the flow of execution due to a thrown exception (that substitutes normal execution flow with an abrupt non-sequential path as shown previously) never reaches the end of the method, the file is left unclosed, which can create serious problems in a program. Consequently, we must ensure that, regardless of whether an exception is thrown or not, the file is closed. This can be achieved by inserting the file closing code inside a finally block, which is always executed regardless of the circumstances. A finally block is executed just after the try-catch blocks have completed (regardless of whether an exception is thrown or whether a matching catch block is found) and just before the code following the try-catch blocks is to be executed.

Listing 19.4 demonstrates three different scenarios where the finally block is executed regardless of the circumstances.

Listing 19.4 TestFinally.cs
01: using System; 02: 03: class Tester 04: { 05:     public static void Main() 06:     { 07:         try 08:         { 09:             Console.WriteLine("Entering Main's try block"); 10:             MyClass myObject = new MyClass(); 11:             myObject.MethodA(); 12:             myObject.MethodB(); 13:             Console.WriteLine("Leaving Main's try block"); 14:         } 15:         catch(Exception exObj) 16:         { 17:             Console.WriteLine("Entering Main's catch block"); 18:             Console.WriteLine(exObj.Message); 19:             Console.WriteLine("Leaving Main's catch block"); 20:         } 21:     } 22: } 23: 24: class MyClass 25: { 26:     public void MethodA() 27:     { 28:         try 29:         { 30:             Console.WriteLine("Entering MethodA's try block"); 31:             int myInt; 32:             int inputInt; 33: 34:             Console.WriteLine("Opening file in MethodA"); 35:             Console.Write("Please enter number: "); 36:             inputInt = Convert.ToInt32(Console.ReadLine()); 37:             myInt = 10 / inputInt; 38:             Console.WriteLine("Leaving MethodA's try block"); 39:         } 40:         catch(DivideByZeroException exObj) 41:         { 42:             Console.WriteLine("Entering MethodA's catch block"); 43:             Console.WriteLine("Exception: " + exObj.Message); 44:             Console.WriteLine("Leaving MethodA's catch block"); 45:         } 46:         finally 47:         { 48:             Console.WriteLine("Closing file in MethodA's finally block"); 49:         } 50:         Console.WriteLine("Leaving MethodA"); 51:     } 52: 53:     public void MethodB() 54:     { 55:         try 56:         { 57:             Console.WriteLine("Entering MethodB's try block"); 58:             int[] myArray = new int[10]; 59:             Console.WriteLine("Opening file"); 60:              //Index of bounds 61:             myArray[34] = 10; 62:             Console.WriteLine("Leaving MethodB's try block"); 63:         } 64:         finally 65:         { 66:             Console.WriteLine("Closing file in MethodB's finally block"); 67:         } 68:         Console.WriteLine("Leaving MethodB"); 69:     } 70: } 

Sample output 1: User enters zero and causes a divide by zero exception in MethodA.

 Entering Main's try block Entering MethodA's try block Opening file in MethodA Please enter number: 0<enter> Entering MethodA's catch block Exception: Attempted to divide by zero. Leaving MethodA's catch block Closing file in MethodA's finally block Leaving MethodA Entering MethodB's try block Opening file Closing file in MethodB's finally block Entering Main's catch block An exception of type System.IndexOutOfRangeException was thrown. Leaving Main's catch block 

Sample output 2: User does not enter zero and avoids the divide by zero exception in MethodA.

 Entering Main's try block Entering MethodA's try block Opening file in MethodA Please enter number: 34 Leaving MethodA's try block Closing file in MethodA's finally block Leaving MethodA Entering MethodB's try block Opening file Closing file in MethodB's finally block Entering Main's catch block An exception of type System.IndexOutOfRangeException was thrown. Leaving Main's catch block 

The Main method calls MethodA and MethodB from within its try block. Any uncaught exceptions passed on from these two method calls will be handled by Main's catch block in lines 15 20, because its parameter class System.Exception is the ultimate base class for any exception class.

MethodA and MethodB both simulate opening a file on their entry (lines 34 and 59) and each file must be closed before each of the methods exits. For that reason, the lines of code that (pretends to) close the files are positioned in finally blocks (lines 46 49 and lines 54 57).

In sample output 1, we cause a divide by zero exception to be generated in line 37 by assigning zero to inputInt. As expected, execution is immediately transferred to the catch block followed by the finally block, after which the execution flow returns to normal.

MethodB demonstrates that even though the try block has no associated catch blocks, its associated finally block is still executed just before the execution flow returns from MethodB. After the finally block has been executed, the exception object is passed over to the Main method where a matching catch block is found. Notice that MethodB causes an IndexOutOfRangeException to be generated and thrown in line 61 because we are attempting to assign 10 to index 34 of myArray, which only has 10 indices.

Sample output 2 shows that even though no exceptions are thrown this time in MethodA, the finally block is still executed. Execution of MethodB in sample output 2 is similar to that of sample output 1.

Note

graphics/common.gif

A try block without any catch blocks (as in MethodB of Listing 19.4) but just a finally block cannot be used to handle exceptions. Instead, this construct is often used with functions that have code, which must be executed before the function exits and that have several return statements dispersed throughout its code. No matter which return statement the method exits with, the finally block is always guaranteed to be executed.



   


C# Primer Plus
C Primer Plus (5th Edition)
ISBN: 0672326965
EAN: 2147483647
Year: 2000
Pages: 286
Authors: Stephen Prata

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