General Catch Block

C# requires that any object that code throws must derive from System.Exception. However, this requirement is not universal to all languages. C++, for example, allows any object type to be thrown, including managed exceptions that don’t derive from System.Exception. All exceptions, whether derived from System.Exception or not, will propagate into C# assemblies as derived from System.Exception.7 The result is that System.Exception catch blocks will catch all exceptions not caught by earlier blocks.

C# also supports a general catch block (catch{ }) that behaves identically to the catch(System.Exception exception) block, except that there is no type or variable name. Also, the general catch block must appear last within the list of catch blocks. Since the general catch block is identical to the catch(System.Exception exception) block and the general catch block must appear last, the compiler issues a warning if both exist within the same try/catch statement because the general catch block will never be invoked.

AdVanced Topic
General Catch Block Internals

The Common Intermediate Language (CIL) code corresponding to a general catch block is, in fact, a catch(object) block. Thus, regardless of the type thrown, the general catch block will catch it. Interestingly, it is not possible to explicitly declare a catch(object) exception block within C# code. Therefore, there is no means of catching a non–System.Exception-derived exception and having an exception instance to scrutinize.

In fact, unmanaged exceptions from languages such as C++ generally result in System.Runtime.InteropServices.SEHException-type exceptions, which derive from the System.Exception type. Therefore, not only can the unmanaged type exceptions be caught using a general catch block, but the non–System.Exception-managed types that are thrown can be caught as well—for instance, types such as string.

Guidelines for Exception Handling

Exception handling provides much-needed structure to the error-handling mechanisms that preceded it. However, it can still lead to some unwieldy results if used haphazardly. The following guidelines offer some best practices for exception handling.

Catch only the exceptions that you can handle.
It is generally possible to handle some types of exceptions but not others. For example, opening a file for exclusive read-write access may throw a System.IO.IOException because the file is already in use. In catching this type of exception, the code can report to the user that the file is in use and allow the user the option of canceling the operation or retrying it. Only exceptions for which there is a known action should be caught. Other exception types should be left for callers higher in the call stack.
Don’t hide (bury) exceptions you don’t fully handle.
New programmers are often tempted to catch all exceptions and then continue executing instead of reporting an unhandled exception to the user. However, this practice may result in a critical system problem going undetected. Unless code takes explicit action to handle an exception or explicitly determines certain exceptions to be innocuous, catch blocks should rethrow exceptions instead of catching them and hiding them from the caller. In most cases, catch(System.Exception) and general catch blocks should occur higher in the call stack unless the block ends by rethrowing the exception.
Use System.Exception and general catch blocks rarely.
Almost all exceptions derive from System.Exception. However, the best way to handle some System.Exceptions is to allow them to go unhandled or to gracefully shut down the application sooner rather than later. These exceptions include cases such as System.OutOfMemoryException and System.StackOverflowException. Fortunately, such exceptions default to a nonrecoverable state, such that catching them without rethrowing them would cause the CLR to rethrow them anyway.8 These exceptions are runtime exceptions that the developer cannot write code to recover from. Therefore, the best course of action is to shut down the application—something the runtime forces.
Avoid exception reporting or logging lower in the call stack.
Often, programmers are tempted to log exceptions or report exceptions to the user at the soonest possible location in the call stack. However, these locations are seldom able to handle the exception fully; instead, they resort to rethrowing the exception. Such catch blocks should not log the exception or report it to a user while in the bowels of the call stack. If the exception is logged and rethrown, the callers higher in the call stack may do the same, resulting in duplicate log entries of the exception. Worse, displaying the exception to the user may not be appropriate for the type of application. (Using System.Console.WriteLine() in a Windows application will never be seen by the user, for example, and displaying a dialog in an unattended command-line process may go unnoticed and freeze the application.) Logging- and exception-related user interfaces should be reserved for use higher up in the call stack.
Use throw; rather than throw <exception object> inside a catch block.
It is possible to rethrow an exception inside a catch block. For example, the implementation of catch(ArgumentNullException exception) could include a call to throw exception. However, rethrowing the exception like this will reset the stack trace to the location of the rethrown call instead of reusing the original throw point location. Therefore, unless you are rethrowing with a different exception type or intentionally hiding the original call stack, use throw; to allow the same exception to propagate up the call stack.
Favor exception conditions to avoid rethrowing an exception inside a catch block.
On occasions when you find yourself catching an exception that you can’t actually handle appropriately and therefore need to rethrow, favor using an exception condition to avoid catching the exception in the first place.
Avoid throwing exceptions from exception filters.
When providing an exception filter, avoid code that throws an exception. Throwing an exception from an exception filter will result in a false condition, and the exception occurrence will be ignored. For this reason, you should consider placing complicated conditional checks into a separate method that is wrapped in a try/catch block that handles the exception explicitly.
Avoid exception conditionals that might change over time.
If an exception filter evaluates conditions such as exception messages that could potentially change with localization or changed message, the expected exception condition will not get caught, unexpectedly changing the business logic. For this reason, you should ensure exception conditions are valid over time.
Use caution when rethrowing different exceptions.
From inside a catch block, rethrowing a different exception will not only reset the call stack but also hide the original exception. To preserve the original exception, set the new exception’s InnerException property, generally assignable via the constructor. Rethrowing a different exception should be reserved for the following situations:
AVOID exception reporting or logging lower in the call stack.
DO NOT over-catch. Exceptions should be allowed to propagate up the call stack unless it is clearly understood how to programmatically address those errors lower in the stack.
CONSIDER catching a specific exception when you understand why it was thrown in a given context and can respond to the failure programmatically.
AVOID catching System.Exception or System.SystemException except in top-level exception handlers that perform final cleanup operations before rethrowing the exception.
DO use throw; rather than throw <exception object> inside a catch block.
DO use exception filters to avoid rethrowing an exception from within a catch block.
DO use caution when rethrowing different exceptions.
AVOID throwing exceptions from exception filters.
AVOID exception filters with logic that might implicitly change over time.


7. Starting with C# 2.0.
8. Starting with Common Language Runtime (CLR) 4. Prior to CLR 4, code should catch such exceptions only to run cleanup or emergency code (such as saving any volatile data) before shutting down the application or rethrowing the exception with throw;.
{{ snackbarMessage }}