In .NET, is there any advantage to a try/catch where the catch just rethrows [duplicate]

StackOverflow https://stackoverflow.com/questions/1207172

  •  05-07-2019
  •  | 
  •  

Question

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;
        }
Was it helpful?

Solution

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.

OTHER TIPS

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.

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

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.

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.

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.

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.

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.

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);
}

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.

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.

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;
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top