C# finally

A finally block is an option of try block and it is used to clean any allocated resources in the try block, for example, finally block can be used to close a opened file or a database connection. Usually the code in a finally block can be run when the control leaves a try statement but if an exception is unhandled, the finally block may not be run.

Syntax:

try
{
	// Code may generate exceptions
}
catch (<ExceptionClass 1> [e1])
{
	// Handle the exception
}
catch (<ExceptionClass 2> [e2])
{
	// Handle the exception
}
...
catch (<ExceptionClass n> [en])
{
	// Handle the exception
}
finally
{
	// Clean up and release resources
}

Example 01-87-01

In this example, we'll add try-catch-finally block to catch the exception thrown in the example 01-99-04 in C# Exception page.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
using System;

interface I { }
public class A : I { }
public class B : I { }

class Program
{
    static void throwInvalidCastException()
    {
        I i = new A();
        B b = (B)i; // InvalidCastException is thrown
    }

    static void Main()
    {
        try
        {
            throwInvalidCastException();
        }
        catch (InvalidCastException e)
        {
            Console.WriteLine("Catch an InvalidCastException.");
        }
        catch (Exception e)
        {
            Console.WriteLine("Catch an Exception.");
        }
        finally
        {
            Console.WriteLine("Running in finally block.");
        }

        Console.Read();
    }
}

Output

Catch an InvalidCastException.
Running in finally block.

Explanation

  • Line 12: InvalidCastException is thrown here.
  • Line 21-24: Catch the InvalidCastException.
  • Line 29-32: The finally block started running before the control left the try block.

Syntax:

try
{
	// Code may generate exceptions
}
finally
{
	// Clean up and release resources
}

Example 01-87-02

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
using System;

public class Program
{
    static void Main()
    {
        test();

        Console.Read();
    }

    static void thrownInvalidCastException()
    {
        object o = "abc";

        try
        {
            int i = (int)o; // InvalidCastException is thrown

            Console.WriteLine("This statement will never be run!");
        }
        finally
        {
            Console.WriteLine("Finally block in thrownInvalidCastException().");
        }
    }

    static void test()
    {
        try
        {
            thrownInvalidCastException();
        }
        catch (ApplicationException e)
        {
            Console.WriteLine("Catch the exception in ApplicationException.");
        }
        finally
        {
            Console.WriteLine("Finally block in test().");
        }
    }
}

Output Error

The program above terminated running with an error message "InvalidCastException was unhandled".

Explanation

  • Line 18: InvalidCastException is thrown here and no catch block after the try block.
  • Line 34-37: InvalidCastException cannot be caught here.
  • Line 7: The control goes to the calling method test(). There is no catch block to catch the exception and then the error message is printed.

In the following example, we'll add catch block in Main() to handle the exception and see what's going on in the finally blocks.

Example 01-87-03

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
using System;

public class Program
{
    static void Main()
    {
        try
        {
            test();
        }
        catch (Exception e)
        {
            Console.WriteLine("Catch the Exception.");
        }
        finally
        {
            Console.WriteLine("Finally in Main().");
        }

        Console.Read();
    }

    static void thrownInvalidCastException()
    {
        object o = "abc";

        try
        {
            int i = (int)o; // InvalidCastException is thrown

            Console.WriteLine("This statement will never be run!");
        }
        finally
        {
            Console.WriteLine("Finally block in thrownInvalidCastException().");
        }
    }

    static void test()
    {
        try
        {
            thrownInvalidCastException();
        }
        catch (ApplicationException e)
        {
            Console.WriteLine("Catch the exception in ApplicationException.");
        }
        finally
        {
            Console.WriteLine("Finally block in test().");
        }
    }
}

Output

Finally block in thrownInvalidCastException().
Finally block in test().
Catch the Exception.
Finally in Main().

Explanation

  • Line 35: After the InvalidCastException thrown in line 29 is caught, the code in this line runs first.
  • Line 51: Then the control goes to the finally block in the calling method test().
  • Line 11-14: The exception is caught here.
  • Line 17: Executes before leaving the try block in Main().

A try block cannot work alone and it must be combined with at least a catch block or a finally block or both.