The .NET Framework allows all .NET languages to take advantage of structured exception handling. Structured exception handling provides a control structure that includes exceptions, protected blocks of code, and filters to allow your code to handle exception robustly and efficiently. You can use try, catch, and finally blocks to detect exceptions thrown within your code and react to them appropriately.

try
{
    // some code that could throw exception
}
catch (SomeException ex)
{
    // code to handle the occurrence of exception
}
finally
{
  // code that gets run always, whether or not an exception was thrown
  // This is usually clean up code that should be executed regardless
  // of whether an exception has been thrown.
}

The try block contains code hat could throw an exception. When en exception is thrown within this block, the first catch block whose filter matches the class of the exception catches it. Note that the filter is specified within the parentheses following the catch keyword. If you have multiple catch blocks, you should ensure that these are ordered from the most specific type to the most generic type. This ensures the most specific type catch block is executed for any given exception.

The finally statement executed, allowing clean up and other code to be executed, regardless of whether an exception is thrown. The finally block even executes if a return, break, or continue statement is executed in the try or catch blocks, or if a goto is used to jump out of the exception handler. This setup allows for a reliable method of cleaning up after the try (and possibly catch) block code executes.
When using specific catch blocks, consider adding a catch block that handles all other exceptions (Exception) if you need to handle any other unexpected exception or make sure that all other exceptions are handled at some point in your code. The following code uses specific catch blocks to handle different exceptions in the appropriate manner.

public void CallCOMMethod()
{
    try
    {
        // Call a method on a COM object.
        myCOMObj.Method1();
    }
    catch (System.Runtime.InteropServices.ExternalException exte)
    {
        // Handle potential COM exceptions arising from this call here.
    }
    catch (InvalidOperationException ae)
    {
        // Handle any potential method calls to the COM object which are
        // not valid in its current state.
    }
    catch (Exception e)
    {
        // Handle other exception that are not handled above.
    }
}

Exception handling in C# is very flexible. It allows you to choose a fine- or coarse-grained approach to error handling and any level between. This means that you can add exception handling around any individual line of code (the fine-grained approach), or around a method that calls many other methods (the coarse-grained approach), or use a mix of the two. When using a fine-grained approach, you can intercept specific exceptions that might be thrown from just a few lines of code. The following method sets an object’s property to a numeric value using fine-grained exception handling:

protected void SetValue(object value)
{
  try
  {
    obj.MyValue = value;
  }
  catch (Exception e)
  {
    // handle potential exception arising from this call here.
  }
}

Consequentially, this approach can add a lot of extra baggage to your code if used throughout your application. This fine-grained approach to exception handling should be used when you have a single line or just a few lines of code that have a high probability of throwing an exception and you need to handle that exception in a specific manner.
Coarse-grained exception handling is quite the opposite; it uses fewer try-catch or try-catch-finally blocks. One example would be to place a try-catch block around all of the code in every public method in an application or component. Doing this allows exceptions to be handled at the highest level in your code. If an exception is thrown at any location in your code, it will be bubbled up the call stack until a catch block is found that can handle it. If try-catch blocks are placed on all public methods (including the Main method), then all exceptions will be bubbled up to these methods and handled. This allows for much less exception handling code to be written, but your ability to handle specific exceptions that may occur in particular areas of your code is diminished. You must determine how best to add exception handling code to your application.
When determining how to structure your exception handling in your application or component, consider doing the following:

  • Use a single try-catch or try-catch-finally exception handler at locations higher up in your code. These exception handlers could be considered coarse-grained.
  • Code farther down the call stack should contain try-finally exception handlers. These exception handlers can be considered fine-grained.

The fine-grained try-finally exception handlers allow for better control over cleaning up after an exception occurs. The exception is then bubbled up to the coarser-grained try-catch or try-catch-finally exception handler. This technique allows for a more centralized scheme of exception handling, and minimizes the code that you have to write to handle exceptions.

You should only catch exceptions when you need to specifically perform any of the following actions:

  • Gather information for debugging
  • Add any relevant information to the exception
  • Execute cleanup code
  • Attemp to recover

If a particular method does not need to perform any of these actions, it should not catch the exception; rather, it should allow it to propagate back up the call stack. This keeps your code clean and explicit as you only catch the exceptions that need to be handled within the scope of a particular method and allow all others to continue to propagate.

Popularity: 8% [?]