Throwing exceptions

When reviewing some code today I noticed some code that catches an exception, does something with it and then explicitly throws it again. The code looked something like this:

try
{
    // Do something that might cause an exception
}
catch (Exception ex)
{
    // Some stuff
    throw ex;
}

The problem with the above code is that when you throw the exception again the details about where the exception originated from are lost because the throw populates that part of the exception object. So the original details are replaced with the details about the current location in the code.

Consider the following program:

static void Main(string[] args)
{
    try
    {
        A();
    }
    catch (Exception ex)
    {
        Console.WriteLine(ex.Message);
        Console.WriteLine(ex.StackTrace);
    }
    Console.ReadLine();
}

private static void A()
{
    B();
}

private static void B()
{
    try
    {
        C();
    }
    catch (Exception ex)
    {
        // I can do something
        Console.WriteLine("Method C() catches the exception and partly handles it");
        Console.WriteLine();
        throw ex;
    }
}

private static void C()
{
    D();
}

private static void D()
{
    Exception ex = new Exception("This exception is thrown in D");
    throw ex;
}

The original exception is thrown by method D. The code in method B catches the exception and partly handles it, it then explicitly throws the original exception again. When the exception is finally caught in the Main method the call stack is truncated to method B. It can no longer see that method C and D were also called.

The output of the application is:

Method C() catches the exception and partly handles it

This exception is thrown in D
   at ConsoleApplication1.Program.B() in d:DevelopmentConsoleApplication1Cons
oleApplication1Program.cs:line 40
   at ConsoleApplication1.Program.A() in d:DevelopmentConsoleApplication1Cons
oleApplication1Program.cs:line 26
   at ConsoleApplication1.Program.Main(String[] args) in d:DevelopmentConsoleA
pplication1ConsoleApplication1Program.cs:line 14

As you can see, the stack trace only goes from the point of the second throw to the point that the exception is caught.

There are two correct solutions to this problem.

Solution 1: Wrapping the Exception

If you have additional information to add to the exception object you can create a brand new Exception and then put the original exception in as an inner exception like this:

try
{
    // Do something that might cause an exception
}
catch(Exception ex)
{
    // Some stuff
    Exception moreDetailedEx = new Exception("A message with more details", ex);
    throw moreDetailedEx;
}

NOTE: Please use a specific exception class and not Exception this makes catching specific types of exception easier and more efficient as the compiler can put in place some optimisations for you over you catching the base Exception class and examining it. I’m using Exception here simply to make the example easier to read.

So, if we change our program above to create a new exception and wrap the old one in it it will now look like this:

static void Main(string[] args)
{
    try
    {
        A();
    }
    catch (Exception ex)
    {
        Console.WriteLine(ex.InnerException.Message);
        Console.WriteLine(ex.InnerException.StackTrace);
        Console.WriteLine();
        Console.WriteLine(ex.Message);
        Console.WriteLine(ex.StackTrace);
    }
    Console.ReadLine();
}

private static void A()
{
    B();
}

private static void B()
{
    try
    {
        C();
    }
    catch (Exception ex)
    {
        // I can do something
        Console.WriteLine("Method C() catches the exception and partly handles it");
        Console.WriteLine();
        Exception newEx = new Exception("This exception is thrown in B", ex);
        throw newEx;
    }
}

private static void C()
{
    D();
}

private static void D()
{
    Exception ex = new Exception("This exception is thrown in D");
    throw ex;
}

I’ve added some extra bits to the Main method to show the InnerException details too. The output of the program now looks like this:

Method C() catches the exception and partly handles it

This exception is thrown in D
   at ConsoleApplication1.Program.D() in d:DevelopmentConsoleApplication1Cons
oleApplication1Program.cs:line 56
   at ConsoleApplication1.Program.C() in d:DevelopmentConsoleApplication1Cons
oleApplication1Program.cs:line 50
   at ConsoleApplication1.Program.B() in d:DevelopmentConsoleApplication1Cons
oleApplication1Program.cs:line 36

This exception is thrown in B
   at ConsoleApplication1.Program.B() in d:DevelopmentConsoleApplication1Cons
oleApplication1Program.cs:line 44
   at ConsoleApplication1.Program.A() in d:DevelopmentConsoleApplication1Cons
oleApplication1Program.cs:line 29
   at ConsoleApplication1.Program.Main(String[] args) in d:DevelopmentConsoleA
pplication1ConsoleApplication1Program.cs:line 14

As you can now see all the information is available. It can now be seen the patch from the final point the exception was caught to the point it was originally thrown.

Solution 2: Re-throwing the Exception

If you do not have any additional information to add to the exception you can simply use the throw keyword on its own and it will keep the existing exception object without altering it. For example:

try
{
    // Do something that might cause an exception
}
catch (Exception ex)
{
    // Some stuff
    throw;
}

Changing our program above to use the throw statement on its own will mean the program now looks like this:

static void Main(string[] args)
{
    try
    {
        A();
    }
    catch (Exception ex)
    {
        Console.WriteLine(ex.Message);
        Console.WriteLine(ex.StackTrace);
    }
    Console.ReadLine();
}

private static void A()
{
    B();
}

private static void B()
{
    try
    {
        C();
    }
    catch (Exception ex)
    {
        // I can do something
        Console.WriteLine("Method C() catches the exception and partly handles it");
        Console.WriteLine();
        throw;
    }
}

private static void C()
{
    D();
}

private static void D()
{
    Exception ex = new Exception("This exception is thrown in D");
    throw ex;
}

And the output now looks like this:

Method C() catches the exception and partly handles it

This exception is thrown in D
   at ConsoleApplication1.Program.D() in d:DevelopmentConsoleApplication1Cons
oleApplication1Program.cs:line 52
   at ConsoleApplication1.Program.C() in d:DevelopmentConsoleApplication1Cons
oleApplication1Program.cs:line 46
   at ConsoleApplication1.Program.B() in d:DevelopmentConsoleApplication1Cons
oleApplication1Program.cs:line 40
   at ConsoleApplication1.Program.A() in d:DevelopmentConsoleApplication1Cons
oleApplication1Program.cs:line 26
   at ConsoleApplication1.Program.Main(String[] args) in d:DevelopmentConsoleA
pplication1ConsoleApplication1Program.cs:line 14

As you can see the stack trace now shows you the entire route between the point the exception was caught and when it was thrown. We can also see from the message that the method C still caught and partly handled the exception.

Using the throw keyword like this actually translates to the CIL (MSIL) rethrow command. When you use throw with an Exception object it translates to the CIL throw command.

When the exception is thrown in D the CIL looks like this:

.method private hidebysig static void D() cil managed
{
    .maxstack 2
    .locals init (
        [0] class [mscorlib]System.Exception ex)
    L_0000: nop
    L_0001: ldstr "This exception is thrown in D"
    L_0006: newobj instance void [mscorlib]System.Exception::.ctor(string)
    L_000b: stloc.0
    L_000c: ldloc.0
    L_000d: throw
}

The key above is L_000d where it throws the exception.

Compare that to method B:

.method private hidebysig static void B() cil managed
{
    .maxstack 1
    .locals init (
        [0] class [mscorlib]System.Exception ex)
    L_0000: nop
    L_0001: nop
    L_0002: call void ConsoleApplication1.Program::C()
    L_0007: nop
    L_0008: nop
    L_0009: leave.s L_0020
    L_000b: stloc.0
    L_000c: nop
    L_000d: ldstr "Method C() catches the exception and partly handles it"
    L_0012: call void [mscorlib]System.Console::WriteLine(string)
    L_0017: nop
    L_0018: call void [mscorlib]System.Console::WriteLine()
    L_001d: nop
    L_001e: rethrow
    L_0020: nop
    L_0021: ret
    .try L_0001 to L_000b catch [mscorlib]System.Exception handler L_000b to L_0020
}

In the above CIL code the key is L_001e where it rethrows the exception. This is where the CIL is much more explicit than C#. In C# the throw keyword is overloaded and functions differently depending on whether it receives an exception object or not.

Training Developers

Software development is a very fast moving business and it is therefore vitally important to keep up with what is happening with technology. If you don’t you could be left behind pretty quickly. When the proverbial hits the fan you don’t want to be left behind.

If you remember back to your school days you might remember Æsop’s fable The Ant and the Grasshopper. The grasshopper did no work in the summer while the ant worked hard in preparation of the lean times. When the lean times came the ant was able to provide for himself, while the grasshopper starved. A lot of software developers are like the grasshopper, they are not planning for their future. You might think it unfair of me to tar all developers with that brush, but I don’t mean to. I did say “a lot” not “all”. So why do I think that?

Last year I spent three months trying to hire a developer. I was shocked at the number of developers that I saw had the attitude that they didn’t need to learn anything unless their employer put them on a training course. Some seemed surprised when I asked how they kept up to date with the industry they are in. Most just mumbled something about reading books and articles online. Given the answers to other questions I don’t think they spent all that much time reading.

Software development knowledge fades faster than ever these days. It seems like only yesterday that I was learning .NET 1.0, yet .NET 4.0 is just around the corner. In a couple of years I’ll be using it commercially. Technologies like LINQ to SQL which has only been released will be dead soon, if recent reports are to be believed. That’s a lot of new information to take in only for it to go stale. This week I’m immersing myself in ASP.NET MVC. I’ve been to a talk on the subject at it looks like that’s the way forward so I want to be at the head of the pack. I’ll also be taking a first look at Subversion this week also. On top of that I’ve got a stack of other things to get through.

When I left university I had the arrogance to think that I knew it all and for a few years I worked on that principle. But that attitude eventually caught up with me and I spent some time unemployed partly as a result of that attitude. I am determined not to let that happen again. These days I am acutely aware of what I don’t know. I think that now I am more aware of my limitations I am a better developer. Because I’m more aware of what I don’t know I strive to fill those gaps by ensuring my own education – I don’t let an employer dictate what I should be learning. I am pro-active and go out there and ensure I’m educated. Of course, if my employer wants to put me on a specific training course I’ll accept it.

I did a little calculation last weekend that surprised me. Actually it shocked the heck out of me. Last year my employer spend roughly £200 on training materials for me. However, I spent a lot more. Of the things that I can remember (so I suppose the things that were worth it) I spent £2500 on my own education.

So, who gets the benefit out of this? For the most part my employer gets the benefit. While I enjoy developing software, it is my employer that profits from it at the end of the day.

Most employer attitudes to training developers are that it isn’t worth it because the developer will just leave with the additional knowledge they’ve received for a higher salary else where. Well, I suppose they will if the employer has that kind of cynical attitude. Employers think that they have to find a replacement soon so why bother training a developer only for another company to take advantage of that. But the a lot of the knowledge that is walking out the door cannot be replaced easily. A lot of the knowledge walking out the door is about the employer’s business and that is unique. You can’t hire that in.

There are a number of “solutions” to this problem. Some employers go for the stick method. “If I train you up and you leave within X months then you have to pay part of the training costs back.” The disturbing thing is that I used to think that was an acceptable solution. But it really isn’t. It is a form of financial handcuffs, and the developer being trained is going to resent it. Quite possibly they’ll be off as soon as the handcuffs are removed or simply not accept the training.

The more reasonable attitude, I think, to take about training is to realise that the developer that’s just been trained has increased their market value. So, pay market value for the developer. You don’t necessarily have to do it straight away, give the training time to sink in if you want, but do increase the developers salary within a few months and don’t tie it to anything else. Don’t roll it in with inflation based increase, an annual increase, or other bonus schemes. Make it very clear that the increase is solely as a result of the greater ability or productivity as a result of the training previously received.