Exception Handling (C# Programming Guide)

A try block is used by C# programmers to partition code that may be affected by an exception, and catch blocks are used to handle any resulting exceptions. A finally block can be used to execute code regardless of whether an exception is thrown. This situation is sometimes necessary because code that follows a try/catch construct will not be executed if an exception is thrown. A try block must be used with either a catch or a finally block, and can include multiple catch blocks. For example:

try
{
    // Code to try here.
}
catch (SomeSpecificException ex)
{
    // Code to handle exception here. 
    // Only catch exceptions you know how to handle. 
    // Never catch base class System.Exception without 
    // rethrowing it at the end of the catch block.
}
try
{
    // Code to try here.
}
finally
{
    // Code to execute after try here.
}
try
{
    // Code to try here.
}
catch (SomeSpecificException ex)
{
    // Code to handle exception here.
}
finally
{
    // Code to execute after try (and possibly catch) here.
}

A try statement without a catch or finally block will cause a compiler error.

Catch Blocks

A catch block can specify an exception type to catch. This type is called an exception filter, and should be a type that is derived from Exception. In general, do not specify Exception in a catch block unless you know for certain how to handle all exceptions that might be thrown in the try block or unless you include a throw statement at the end of your catch block.

Multiple catch blocks with different exception filters can be chained together. Multiple catch blocks are evaluated from top to bottom, but only one catch block is executed for each exception thrown. The first catch block that species the exact type or a base class of the thrown exception will be executed. If no catch block specifies a matching exception filter, a catch block without a filter (if any) will be executed. It is important to position catch blocks with the most specific, that is, the most derived, exception classes first.

You should catch exceptions when the following conditions are true:

  • You have a specific understanding of why the exception was thrown, and can implement a specific recovery, such as catching a FileNotFoundException object and prompting the user to enter a new file name.

  • You can create and throw a new, more specific exception. For example:

    int GetInt(int[] array, int index)
    {
        try
        {
            return array[index];
        }
        catch(System.IndexOutOfRangeException e)
        {
            throw new System.ArgumentOutOfRangeException(
                "Parameter index is out of range.");
        }
    }
    
  • To partially handle an exception. For example, a catch block could be used to add an entry to an error log, but then re-throw the exception to enable subsequent handling of the exception. For example:

    try
    {
        // try to access a resource
    }
    catch (System.UnauthorizedAccessException e)
    {
        LogError(e);  // call a custom error logging procedure 
        throw e;      // re-throw the error
    }
    

Finally Blocks

A finally block enables clean-up of actions performed in a try block. If present, the finally block executes after the try and catch blocks execute. A finally block is always executed, regardless of whether an exception is thrown or whether a catch block matching the exception type is found.

The finally block can be used to release resources such as file streams, database connections, and graphics handles without waiting for the garbage collector in the runtime to finalize the objects. See using Statement (C# Reference) for more information.

In this example, the finally block is used to close a file opened in the try block. Notice that the state of the file handle is checked before it is closed. If the try block did not open the file, the file handle will still be set to null. Alternatively, if the file is opened successfully and no exception is thrown, the finally block will still be executed and will close the open file.

System.IO.FileStream file = null;
System.IO.FileInfo fileinfo = new System.IO.FileInfo("C:\\file.txt");
try
{
    file = fileinfo.OpenWrite();
    file.WriteByte(0xF);
}
finally
{
    // check for null because OpenWrite 
    // might have failed 
    if (file != null)
    {
        file.Close();
    }
}

C# Language Specification

For more information, see the following sections in the C# Language Specification:

  • 16 Exceptions

  • 8.9.5 The throw statement

  • 8.10 The try Statement

See Also

Concepts

C# Programming Guide

Reference

Exceptions and Exception Handling (C# Programming Guide)

try-catch (C# Reference)

try-finally (C# Reference)

try-catch-finally (C# Reference)

Other Resources

C# Reference