Share via


Exceptions Overview

An exception is any error condition or unexpected behavior encountered by an executing program. Exceptions can be raised because of a fault in your code or in code you call (such as a shared library), unavailable operating system resources, unexpected conditions the common language runtime encounters (such as code that cannot be verified), and so on. Your application can recover from some of these conditions, but not others. While you can recover from most application exceptions, you cannot recover from most runtime exceptions.

In the .NET Framework, an exception is an object that inherits from the Exception Class class. An exception is thrown from an area of code where a problem has occurred. The exception is passed up the stack until the application handles it or the program terminates. For more information on handling exceptions using the .NET Framework, see the Exception Class topic.

How the Runtime Manages Exceptions

The runtime uses an exception handling model based on exception objects and protected blocks of code. An Exception object is created to represent an exception when it occurs.

The runtime creates an exception information table for each executable. Each method of the executable has an associated array of exception handling information (which can be empty) in the exception information table. Each entry in the array describes a protected block of code, any exception filters associated with that code, and any exception handlers (catch statements). This exception table is extremely efficient and there is no performance penalty in processor time or in memory use when an exception does not occur. You use resources only when an exception occurs.

The exception information table represents four types of exception handlers for protected blocks:

  • A finally handler that executes whenever the block exits, whether that occurs by normal control flow or by an unhandled exception.
  • A fault handler that must execute if an exception occurs, but does not execute on completion of normal control flow.
  • A type-filtered handler that handles any exception of a specified class or any of its derived classes.
  • A user-filtered handler that runs user-specified code to determine whether the exception should be handled by the associated handler or should be passed to the next protected block.

Each language implements these exception handlers according to its specifications. For example, Visual Basic .NET provides access to the user-filtered handler through a variable comparison (using the When keyword) in the catch statement; C# does not implement the user-filtered handler.

When an exception occurs, the runtime begins a two-step process:

  1. The runtime searches the array for the first protected block that:

    • Protects a region that includes the currently executing instruction, and
    • Contains an exception handler or contains a filter that handles the exception.
  2. If a match occurs, the runtime creates an Exception object that describes the exception. The runtime then executes all finally or fault statements between the statement where the exception occurred and the statement handling the exception. Note that the order of exception handlers is important: the innermost exception handler is evaluated first. Also note that exception handlers can access the local variables and local memory of the routine that catches the exception, but any intermediate values at the time the exception is thrown are lost.

    If no match occurs in the current method, the runtime searches each caller of the current method, and it continues this path all the way up the stack. If no caller has a match, the runtime allows the debugger to access the exception. If the debugger does not attach to the exception, the runtime raises the UnhandledException event. If there are no listeners for the UnhandledException event, the runtime dumps a stack trace and ends the program.

Filtering Runtime Exceptions

You can filter the exceptions you catch and handle either by type or by some user-defined criteria.

Type-filtered handlers handle a particular type of exception (or classes derived from it). The most common form of type-filtered exception handler specifies that only a particular class of exception be caught.

The following example shows an exception handler designed to catch a specific exception, in this case the FileNotFoundException.

Catch e As FileNotFoundException
   Console.WriteLine("[Data File Missing] {0}", e)
[C#]
catch(FileNotFoundException e) {
    Console.WriteLine("[Data File Missing] {0}", e);
}

User-filtered exception handlers catch and handle exceptions based on requirements you define for the exception. These handlers use the try/except block in the Managed Extensions for C++ or the Catch statement with the When keyword in Visual Basic .NET. For details on filtering exceptions in this way, see Using Specific Exceptions in a Catch Block.

See Also

Exception Class | Exception Hierarchy | Exception Handling Fundamentals | Best Practices for Handling Exceptions | Handling and Throwing Exceptions