Handling and Throwing Exceptions
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 re-throw the original exception. When a catch block re-throws an exception, some of the debugging information that was placed on the call stack before the re-throw 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 re-throw occurred. You should catch an exception only when some action needs to be taken in addition to, or instead of, re-throwing 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, attempt to match catch blocks with specific types of exceptions. This is preferable to having a general catch block that re-throws 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. It assumes you have resolved an instance of the ExceptionManager class through the Enterprise Library container and saved it in a variable named exManager. For more information on instantiating objects, see Creating and Referencing Enterprise Library Objects.
try
{
// Run code.
}
catch(DataAccessException ex)
{
bool rethrow = exManager.HandleException(ex, "Data Access Policy");
if (rethrow)
{
throw;
}
}
'Usage
Try
' Run code.
Catch ex As DataAccessException
Dim rethrow As Boolean = exManager.HandleException(ex, "Data Access Policy")
If (rethrow) Then
Throw
End If
End Try
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 other information in addition to 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. It assumes you have resolved an instance of the ExceptionManager class through the Enterprise Library container and saved it in a variable named exManager. For more information on instantiating objects see Creating and Referencing Enterprise Library Objects.
'Usage
Try
' Execute code.
Catch ex As SqlException When ex.Number = 1204
Dim rethrow As Boolean = exManager.HandleException(ex, "Data Access Policy")
If (rethrow) Then
Throw
End If
End Try
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.