The difference between try/catch/throw and try/catch(e)/throw e

C#Exception Handling

C# Problem Overview


What is the difference between

try { }
catch
{ throw; }

and

try { }
catch(Exception e)
{ throw e;}

?

And when should I use one or the other?

C# Solutions


Solution 1 - C#

The constructions

try { ... }
catch () { ... } /* You can even omit the () here */

try { ... }
catch (Exception e) { ... }

are similar in that both will catch every exception thrown inside the try block (and, unless you are simply using this to log the exceptions, should be avoided). Now look at these:

try { ... }
catch ()
{
    /* ... */
    throw;
}

try { ... }
catch (Exception e)
{
    /* ... */
    throw;
}

try { ... }
catch (Exception e)
{
    /* ... */
    throw e;
}

The first and second try-catch blocks are EXACTLY the same thing, they simply rethrow the current exception, and that exception will keep its "source" and the stack trace.

The third try-catch block is different. When it throws the exception, it will change the source and the stack trace, so that it will appear that the exception has been thrown from this method, from that very line throw e on the method containing that try-catch block.

Which one should you use? It really depends on each case.

Let's say you have a Person class with a .Save() method that will persist it into a database. Let's say that your application executes the Person.Save() method somewhere. If your DB refuses to save the Person, then .Save() will throw an exception. Should you use throw or throw e in this case? Well, it depends.

What I prefer is doing:

try {
    /* ... */
    person.Save();
}
catch(DBException e) {
    throw new InvalidPersonException(
       "The person has an invalid state and could not be saved!",
       e);
}

This should put the DBException as the "Inner Exception" of the newer exception being throw. So when you inspect this InvalidPersonException, the stack trace will contain info back to the Save method (that might be sufficient for you to solve the problem), but you still have access to the original exception if you need it.

As a final remark, when you are expecting an exception, you should really catch that one specific exception, and not a general Exception, ie, if you are expecting an InvalidPersonException you should prefer:

try { ... }
catch (InvalidPersonException e) { ... }

to

try { ... }
catch (Exception e) { ... }

Good luck!

Solution 2 - C#

The first preserves the stack trace while the second resets it. This means that if you use the second approach the stack trace of the exception will always start from this method and you will lose the original exception trace which could be disastrous for someone reading exception logs as he will never find out the original cause of the exception.

The second approach might be useful when you want to add additional information to the stack trace but it is used like this:

try
{
    // do something
}
catch (Exception ex)
{
    throw new Exception("Additional information...", ex);
}

There's a blog post discussing the differences.

Solution 3 - C#

You should use

try { }
catch(Exception e)
{ throw }

if you want to do something with the exception before re-throwing it (logging for example). The lonely throw preserves stack trace.

Solution 4 - C#

The difference between a parameterless catch and a catch(Exception e) is that you get a reference to the exception. From framework version 2 unmanaged exceptions are wrapped in a managed exception, so the parameterless exception is no longer useful for anything.

The difference between throw; and throw e; is that the first one is used to rethrow exceptions and the second one is used to throw a newly created exception. If you use the second one to rethrow an exception, it will treat it like a new exception and replace all stack information from where it was originally thrown.

So, you shold not use either of the alternatives in the question. You should not use the parameterless catch, and you should use throw; to rethrow an exception.

Also, in most cases you should use a more specific exception class than the base class for all exceptions. You should only catch the exceptions that you anticipate.

try {
   ...
} catch (IOException e) {
   ...
   throw;
}

If you want to add any information when rethrowing the exception, you create a new exception with the original exception as an inner exception to preservere all information:

try {
   ...
} catch (IOException e) {
   ...
   throw new ApplicationException("Some informative error message", e);
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionKarimView Question on Stackoverflow
Solution 1 - C#Bruno ReisView Answer on Stackoverflow
Solution 2 - C#Darin DimitrovView Answer on Stackoverflow
Solution 3 - C#Otávio DécioView Answer on Stackoverflow
Solution 4 - C#GuffaView Answer on Stackoverflow