Handling and Throwing Exceptions

Retired Content

This content is outdated and is no longer being maintained. It is provided as a courtesy for individuals who are still using these technologies. This page may contain URLs that were valid when originally published, but now link to sites or pages that no longer exist.

The latest Enterprise Library information can be found at the Enterprise Library site.

When an exception occurs, it passes up the stack and each catch block can potentially handle it. The order of catch statements is important. Put catch blocks that target specific exceptions before a general catch block. Otherwise, the compiler might issue an error. The common language runtime (CLR) determines the proper catch block by matching the type of the exception to the name of the exception specified in the catch block. If there is no specific catch block, a general catch block, if it exists, handles the exception.

Debugging and Exception Propagation

The CLR catches exceptions that are not caught by a catch block (these exceptions are considered to be unhandled exceptions). When you debug your application using the Visual Studio debugger, the debugger stops execution at the stack trace location where the unhandled exception occurred. This allows you to examine local variables and navigate through the execution stack.

Note

You should avoid writing catch blocks that do nothing but rethrow the original exception. When a catch block rethrows an exception, some of the debugging information that was placed on the call stack before the rethrow occurred is lost. For example, if you debug your application using a minidump file that contains a subset of the information contained in a crash dump file, or if you attach a debugger to a process after an unhandled exception, you cannot interrogate stack elements such as the local variables, that were placed on the call stack before the rethrow occurred. You should catch an exception only when some action needs to be taken in addition to, or instead of, rethrowing the original exception.

To avoid catching exceptions that your catch block does not process, you should write catch blocks that are specific to exception types. If you are developing using Visual Basic or the Managed Extensions to C++, you can also use user-filtered exceptions.

Handling Specific Exceptions

As far as possible, try to match catch blocks with specific types of exceptions. This is preferable to having a general catch block that rethrows exception types that no other catch block processes. This approach makes the intent of the catch blocks clear, and the call stack remains available under the debugger for other exception types.

The following code shows how to handle exceptions of a custom type named DataAccessException. In the example, this exception causes a policy named Data Access Policy to be applied.

try
{
  // Run code.
}
catch(DataAccessException ex)
{
  bool rethrow = ExceptionPolicy.HandleException(ex, "Data Access Policy");
  if (rethrow)
  {
    throw;
  }
}
'Usage
Try
  ' Run code.
Catch ex As DataAccessException
  Dim rethrow As Boolean = ExceptionPolicy.HandleException(ex, "Data Access Policy")
  If (rethrow) Then
    Throw
  End If

Note

If you use the Unity Integration approach to create instances of objects from the Exception Handling Application Block, you must use the non-static façade named ExceptionManager. This class exposes the same API as the ExceptionPolicy class static façade. For more information about using the Unity Application Block to create and inject instances of Enterprise Library objects, see Creating Objects Using the Unity Application Block.

User-Filtered Exceptions

Visual Basic and the Managed Extensions to C++ support user-filtered exceptions. User-filtered exception handlers catch and handle exceptions based on additional information besides the exception type. The additional information allows you to create catch blocks that are more precise than catch blocks that use only the exception type.

Visual Basic user-filtered exception handlers use the Catch statement in conjunction with the When keyword. The additional information included in the When clause means that if the When clause is true, the catch block handles only the specific exceptions it was designed for. In situations where the When clause is false, the catch block is not entered. This means that the exception is not caught and the call stack is preserved when you are using the debugger.

This technique is useful when a single exception object corresponds to multiple errors. In this case, the exception object typically has a property that contains the specific error code associated with the error. You can use the error code property in the expression to select only the particular error you want to handle in that Catch statement.

The following Visual Basic example illustrates the Catch/When statement.

'Usage
Try
  ' Execute code.
Catch ex As SqlException When ex.Number = 1204
  Dim rethrow As Boolean = ExceptionPolicy.HandleException(ex, "Data Access Policy")
  If (rethrow) Then
    Throw
  End If
End Try

Note

If you use the Unity Integration approach to create instances of objects from the Exception Handling Application Block, you must use the non-static façade named ExceptionManager. This class exposes the same API as the ExceptionPolicy class static façade. For more information about using the Unity Application Block to create and inject instances of Enterprise Library objects, see Creating Objects Using the Unity Application Block.

To see how to use user-filtered exceptions with the Managed Extensions to C++, see Using User-Filtered Exceptions.

For more exception handling recommendations, see Best Practices for Handling Exceptions.