Are You Throwing Exceptions Correctly?

We generally use exception and stack trace for tracking down to the problem in our code. But a lots of the time, in case you are not using proper way to throw exceptions then it might make difficult to narrow down the problem. Whenever we throw an exception; it is recorded into the exception stack trace.

Let understand this with an example. Consider the below console application:

using System;
using System.Text;

namespace ExceptionTest
{
  class Program
  {
    static void Main(string[] args)
    {
      new ExceptionTester().FirstCall();
    }
  }

  public class ExceptionTester
  {
    public void FirstCall()
    {
      try
      {
        SecondCall();
      }
      catch(Exception ex)
      {
        Console.WriteLine(ex.StackTrace);
      }
    }

    public void SecondCall()
    {
      try
      {
        ThirdCall();
      }
      catch
      {
        throw;
      }
    }

    public void ThirdCall()
    {
      try
      {
        ForthCall();
      }
      catch
      {
        throw;
      }
    }

    public void ForthCall()
    {
      int d = 0;
      int x = 10 / d;
    }
  }
}

You may see the that the initially the FirstCall() method is called which internally calling SecondCall() > ThirdCall() > ForthCall() and the ForthCall is generating System.DivideByZeroException exception. Each function is throwing the exception by using throw keyword. Output of the above program will be:

Attempted to divide by zero.
   at ExceptionTest.ExceptionTester.ForthCall() in C:\\ExceptionTest\\Program.cs:line 56
   at ExceptionTest.ExceptionTester.ThirdCall() in C:\\ExceptionTest\\Program.cs:line 49
   at ExceptionTest.ExceptionTester.SecondCall() in C:\\ExceptionTest\\Program.cs:line 37
   at ExceptionTest.ExceptionTester.FirstCall() in C:\\ExceptionTest\\Program.cs:line 20

By looking at above stack trace you could easily track down the root cause of the problem. Method ForthCall() is the culprit.

Do not Throw Same Exception

A lots of time its common mistake to throw same exception again instead of re-throwing it. Look at below bad practice of coding:

using System;
using System.Text;

namespace ExceptionTest
{
  class Program
  {
    static void Main(string[] args)
    {
      new ExceptionTester().FirstCall();
    }
  }

  public class ExceptionTester
  {
    public void FirstCall()
    {
      try
      {
        SecondCall();
      }
      catch(Exception ex)
      {
        Console.WriteLine(ex.Message);
        Console.WriteLine(ex.StackTrace);
      }
    }

    public void SecondCall()
    {
      try
      {
        ThirdCall();
      }
      catch(Exception ex)
      {
        throw ex;
      }
    }

    public void ThirdCall()
    {
      try
      {
        ForthCall();
      }
      catch (Exception ex)
      {
        throw ex;
      }
    }

    public void ForthCall()
    {
      int d = 0;
      int x = 10 / d;
    }
  }
}

"throw ex;" is basically throwing the same exception again instead of re-throwing the original exception. Because of this the all exception stack trace information is lost till this point and stack started to build again. The output of above program will be:

Attempted to divide by zero.
   at ExceptionTest.ExceptionTester.SecondCall() in C:\\ExceptionTest\\Program.cs:line 37
   at ExceptionTest.ExceptionTester.FirstCall() in C:\\ExceptionTest\\Program.cs:line 20

You can see we can only see methods SecondCall() and FirstCall() in the exception stack. Final conclusion of this whole article is to be careful while throwing exception.

10 comment(S)


Will on Jul 25, 2008 11:37 AM

You forgot the most important example: throw.

...catch(Exception ex)
{
Console.WriteLine(ex.Message);
throw;
}

which rethrows the exception but preserves the stack trace.

Nikola Malovic on Jul 30, 2008 05:01 AM

throw; also eats part of stack

I have blogged about it here: http://blog.vuscode.....eption-handling.aspx

Justin on Jul 30, 2008 07:55 AM

Thanks for the great post. I learned this the hard way. I had used 'throw ex' extensively in a project which made it very hard to manage once bug reports started rolling in. Live and learn I guess.

asp.net on Jul 30, 2008 02:50 PM

good article.

Aaron on Jul 30, 2008 08:22 PM

I think 'throw;' still messes with the stack trace some. Better than 'throw ex;' though.

Brent on Jul 31, 2008 08:36 AM

Fourth

BlueG on Sep 30, 2008 04:41 AM

How should I proceed, if i want to add info to exception and then re-throw it? Could be it this way?

...
catch(Exception ex)
{
throw new Exception("In executed methods occured bug!", ex);
}

Leave a comment