tags:

views:

562

answers:

12

Possible Duplicate:
Why catch and rethrow Exception in C#?

I sometimes come across C# code that looks like this:

        try
        {
            // Some stuff
        }
        catch (Exception e)
        {
            throw e;
        }

I understand its possible to do something like log the exception message and then rethrow it. I'm talking about a catch that only rethrows the exception. I don't see a point to this. I have three questions:

1) Is there any advantage to this

2) Does this slow doen the code at all

3) Would it make any difference if the catch block were as follows:

        catch (Exception)
        {
            throw;
        }
+3  A: 

Not if you do nothing else in the catch... But this is often used to do other things in the catch, such as logging, or other kinds of exception procesing, before rethrowing it.

Charles Bretana
+17  A: 

This rethrows the exact same exception:

    catch (Exception)
    {
        throw;
    }

Whereas this rethrows the exception without the original stack trace:

    catch (Exception e)
    {
        throw e;
    }

There is often a good reason for throw; as you can log the exception or do other things prior to rethrowing the exception. I am not aware of any good reasons for throw e; as you will wipe out the valuable stack trace information.

Andrew Hare
And the latter should almost never be used, though one could argue the former should never be used in the incarnation you presented either (without adding at least some form of logging to the mix).
Chris
@Andrew, As I understood this, the variable e IS a pointer to the same exception object on the Heap... Are you saying that a new Exception object is created on the Heap? or simply that a new ref variable "e" is created? If the former, Do you have a reference for this tidbit?
Charles Bretana
@Charles - Good to point out - I always assumed that it was a new exception but some investigation helped me learn that it is in fact the same exact exception instance in both cases.
Andrew Hare
@Andrew, I'm curious then, (and I will do some more research on this), about why the first syntax includes the stack trace but the second syntax looses it?
Charles Bretana
Personally I'm a fan of inner exceptions for this. Throw a new exception with your own message, but attach the exception that was the original cause of the error.
Nate C-K
A: 

Sure.

Most often you want to log the exception before throwing it, and perhaps record some variable values from the method.

Just catching it to throw it, though, doesn't gain you a whole lot.

routeNpingme
A: 

Just like that, no. However, you may want to do this:

catch (Exception ex)
{
     LogException(ex);
     throw;
}

Where LogException() is a custom class that, erm, logs the exception or emails an alert or something.

Dan Diplo
+2  A: 

I use that technique so I can put a breakpoint on the throw when debugging. Sometimes I remove it after I'm done...

Why not just use the stacktrace to determine the line of code in where the throw gets generated?
Justin Dearing
This trick isn't about knowing where the exceptions are being thrown (you could turn on CLR Exception debugging for that) - when you have a breakpoint, you have QuickWatch and that's usually enough to resolve the cause of the exception.
+2  A: 

The main difference is that the stack trace of the exception will be altered to show that it originated from the location of the try-catch in the first example.

The second example maintains the stack trace.

Garry Shutler
+1  A: 

1 - I don't see any advantage at all. If you're not handling the exception, leave the try/catch off. The other problem with this example is that you're not throwing the actual exception, but a new one.

2 - yes - but unless this is sitting in a big loop of repeated code, you likely won't notice a difference.

3 - Yes. In the first example, you're messing with your call stack. This example keeps the stack intact by bubbling up the exception, instead of throwing a new one.

Scott Ivey
A: 

I think the point is to ensure that only one TYPE of exception is thrown. It's a pretty bad anti-pattern IMHO

e.g.

try
{
    throw XYZ();
}
catch(Exception e)
{
    throw e;
}
Glen
That makes no sense.
Will
Would that not catch an exception of any type and just rethrow it?
Justin Dearing
that's why the statement doesn't make any sense.
Will
It'll catch an exception of any type and rethrow it as an exception of type "Exception", thur removing type info. I think.
Glen
+1  A: 

If you're really doing nothing else, there's only one advantage I've ever found: you can put a breakpoint on the throw line. It makes it very specific (rather than just breaking whenever that exception type is thrown).

I'd only do that while debugging though, then revert the code back.

Jon Skeet
+1  A: 

Is there an advantage

Generally speaking no. All this pattern will do is reset the stack trace to the point of the new throw. This will just make it more difficult for developers to track down the source of the problem

Does it slow down the code at all

At all? Possibly. Slow it down by any measurable difference? No.

Would it make any difference if the catch block were as follows?

Yes, that catch is essentially completely redundant. It will rethrow the exception which will maintain the original stack trace and have no percievable impact on your application.

JaredPar
+1  A: 

It's often nice for logging. Also if you leave off the argument in the re-throw then it doesn't alter the stack trace of e.

Sometimes you want to allow through certain types e.g. here's special processing for everything but FooException:

try
{
    // ...
}
catch (FooException)
{
    throw;
}
catch (Exception ex)
{
    // handle differently, like wrap with a FooException
    throw new FooException("I pitty the Foo.", ex);
}
McKAMEY
A: 

I wrote up a quick test to show the differences. Here is the test code:

try
{
    var broken = int.Parse("null");
}
catch (Exception ex1)
{
    System.Diagnostics.Trace.WriteLine(ex1.ToString());
}

try
{
    try
    {
        var broken = int.Parse("null");
    }
    catch (Exception)
    {
        throw;
    }
}
catch (Exception ex2)
{
    System.Diagnostics.Trace.WriteLine(ex2.ToString());
}

try
{
    try
    {
        var broken = int.Parse("null");
    }
    catch (Exception ex3)
    {
        throw ex3;
    }
}
catch (Exception ex4)
{
    System.Diagnostics.Trace.WriteLine(ex4.ToString());
}

Running this, I get the following output:

A first chance exception of type 'System.FormatException' occurred in mscorlib.dll
System.FormatException: Input string was not in a correct format.
   at System.Number.StringToNumber(String str, NumberStyles options, NumberBuffer& number, NumberFormatInfo info, Boolean parseDecimal)
   at System.Number.ParseInt32(String s, NumberStyles style, NumberFormatInfo info)
   at System.Int32.Parse(String s)
   at QuickTests.Program.Main(String[] args) in C:\Projects\Test\QuickTests\Program.cs:line 18
A first chance exception of type 'System.FormatException' occurred in mscorlib.dll
A first chance exception of type 'System.FormatException' occurred in QuickTests.exe
System.FormatException: Input string was not in a correct format.
   at System.Number.StringToNumber(String str, NumberStyles options, NumberBuffer& number, NumberFormatInfo info, Boolean parseDecimal)
   at System.Number.ParseInt32(String s, NumberStyles style, NumberFormatInfo info)
   at System.Int32.Parse(String s)
   at QuickTests.Program.Main(String[] args) in C:\Projects\Test\QuickTests\Program.cs:line 33
A first chance exception of type 'System.FormatException' occurred in mscorlib.dll
A first chance exception of type 'System.FormatException' occurred in QuickTests.exe
System.FormatException: Input string was not in a correct format.
   at QuickTests.Program.Main(String[] args) in C:\Projects\Test\QuickTests\Program.cs:line 49

You'll notice that the first two exceptions are work the same way. So, "throw;" doesn't change anything as far as the exception that moves up the stack. However "throw ex3;" causes the reported exception to be different, changing the stack trace for the exception.

John Fisher