views:

2427

answers:

8

What are the best practices to consider when catching exceptions, and re-throwing them. I want to make sure that the Exception object's InnerException and stack trace are preserved. Is there a difference between the following code blocks in how they handle this?

try
{
    //some code
}
catch (Exception ex)
{
    throw ex;
}

//......

try
{
    //some code
}
catch
{
    throw;
}
+33  A: 

The way to preserve the stack trace is through the use of the throw; This is valid as well

try {
  // something that boms here
} catch (Exception ex)
{
    throw;
}

throw ex; is basically like throwing an exception from that point, so the stack trace would only go to where you are issuing the throw ex; statement

@Mike is also correct, assuming the exception allows you to pass an exception (which is recommended).

Karl Seguin has a great write up on exception handling in his foundations of programming e-book as well, which is a great read.

Darren Kopp
That exception handling writeup is wonderful. Thank you for sharing.
SpacePenguin
I'm not so sure if that write-up is wonderful, it suggests try { // ... } catch(Exception ex) { throw new Exception(ex.Message + "other stuff"); } is good. The problem is that you're completely unable to handle that exception any further up the stack, unless you catch all exceptions, a big no-no (you sure you want to handle that OutOfMemoryException?)
kronoz
+2  A: 

When you throw ex, you're essentially throwing a new exception, and will miss out on the original stack trace information. throw is the preferred method.

Forgotten Semicolon
+6  A: 

The rule of thumb is to avoid Catching and Throwing the basic Exception object. This forces you to be a little smarter about exceptions; in other words you should have an explicit catch for a SqlException so that your handling code doesn't do something wrong with a NullReferenceException.

In the real world though, catching and logging the base exception is also a good practice, but don't forget to walk the whole thing to get any InnerExceptions it might have.

swilliams
I think it's best to deal with unhandled exceptions for logging purposes by using the AppDomain.CurrentDomain.UnhandledException and Application.ThreadException exceptions. Using big try { ... } catch(Exception ex) { ... } blocks everywhere means a lot of duplication. Depends whether you want to log handled exceptions, in which case (at least minimal) duplication might be inevitable.
kronoz
Plus using those events means you *do* log all unhandled exceptions, whereas if you use big ol' try { ... } catch(Exception ex) { ... } blocks you might miss some.
kronoz
+12  A: 

If you throw a new exception with the initial exception you will preserve the initial stack trace too..

try{
} 
catch(Exception ex){
     throw new MoreDescriptiveException("here is what was happening", ex);
}
Mike
A: 

I would definitely use:

try
{
    //some code
}
catch
{
    throw;
}

That will preserve your stack.

1kevgriff
+1  A: 

You may also use:

try
{
// Dangerous code
}
finally
{
// clean up, or do nothing
}

And any exceptions thrown will bubble up to the next level that handles them.

Erick B
+1  A: 

Maybe I am missing something but I wrote a sample program

namespace MyException
{
    class Program
    {   

        static void foo()
        {
            try
            {
                int[] myArray = new int[2] { 0, 1 };
                Console.WriteLine("Array value:{0}", myArray[2]);

            }
            catch (System.Exception e)
            {
                //throw e;
                //throw;
                throw new System.IndexOutOfRangeException();
            }
        }


        static void Main(string[] args)
        {
            Console.WriteLine("We are testing the re-throw handling in C#");
            foo();
        }
    }
}

and I see the same behaviour no matter which re-throw I use.

I also made this mistake - see here: http://stackoverflow.com/questions/730250/is-there-a-difference-between-throw-and-throw-ex/776756#776756
Shaul
A: 

You should always use "throw;" to rethrow the exceptions in .NET,

Refer this, http://weblogs.asp.net/bhouse/archive/2004/11/30/272297.aspx

Basically MSIL (CIL) has two instructions - "throw" and "rethrow" and C#'s "throw ex;" gets compiled into MSIL's "throw" and C#'s "throw;" - into MSIL "rethrow"! Basically I can see the reason why "throw ex" overrides the stack trace.

Vinod T. Patil