C Sharp

Designing Your Code with Exception Handling

So far, we've covered the basic concepts of using exception handling and the semantics related to the throwing and catching of exceptions. Now let's look at an equally important facet of exception handling: understanding how to design your system with exception handling in mind. Suppose you have three methods: Foo, Bar, and Baz. Foo calls Bar, which calls Baz. If Baz publishes the fact that it throws an exception, does Bar have to catch that exception even if it can't, or won't, do anything with it? How should code be split with regards to the try and catch blocks? -

Design Issues with the try Block

You know how to catch an exception that a called method might throw, and you know that control passes up the call stack until an appropriate catch block is found. So the question is, should a try block catch every possible exception that a method within it can throw? The answer is no, to maintain the biggest benefits of using exception handling in your applications: reduced coding and lower maintenance costs. The following example illustrates a program where a catch is rethrown, to be handled by another catch block.

using System;
class WhenNotToCatchApp
{
    public void Foo()
    {
        try
        {
            Bar();
        }
        catch(Exception e)
        {
            Console.WriteLine(e.Message);
        }
    }
    public void Bar()
    {
        try
        {
            Baz();
        }
        catch(Exception e)
        {
// Bar should catch this because it
// doesn't do anything but rethrow it.
throw;
        }
    }
    public void Baz()
    {
        throw new Exception("Exception originally thrown by Baz");
    }
    public static void Main()
    {
        WhenNotToCatchApp test = new WhenNotToCatchApp();
        test.Foo(); // This method will ultimately
                    // print the error message.
    }
}

In this example, Foo catches the exception that Baz throws even though it then does nothing except rethrow the exception back up to Bar. Bar then catches the rethrown exception and does something with the information-in this case, displaying the Exception object's error message property. Following are a few reasons why methods that simply rethrow an exception should not catch that exception in the first place: -

  • Because the method doesn't do anything with the exception, you'd be left with a catch block in the method that is superfluous at best. Obviously, it's never a good idea for code to exist when it has absolutely no function.
  • If the exception type being thrown by Baz were to change, you'd have to go back and change both the Bar catch block and the Foo catch block. Why put yourself in a situation in which you'd have to alter code that doesn't even do anything?

Because the CLR automatically continues up the call stack until a method catches the exception, intermediate methods can ignore the exceptions that they cannot process. Just make sure in your design that some method catches the exception because, as mentioned earlier, if an exception is thrown and no catch block is found in the current call stack, the application will abort.