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

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!

Leave a Comment