Difference between try / catch / throw and try / catch (e) / throw e

What's the difference between

try { } catch { throw; } 

and

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

?

And when should I use one or the other?

+82
c # exception-handling
Nov 08 '09 at 17:18
source share
4 answers

Constructions

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

similar in that both will catch every exception that is thrown inside the try block (and if you just don't use this to log exceptions, you should avoid it ). Now let's look at them:

 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 just reconstruct the current exception, and this exception will save its "source" and the stack trace.

The third try-catch block is different. When it throws an exception, it will change the trace of the source and stack, so that it appears that the exception was selected from this method from this very line throw e in the method containing this try-catch block.

What benefits should you use? It really depends on each case.

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

I prefer to do:

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

This should put a DBException as an "Internal exception" for the new exception. Therefore, when you check for this InvalidPersonException, the stack trace will contain information back to the Save method (this may be enough to solve the problem), but you still have access to the original exception if you need it.

As a final note, when you are expecting an exception, you should really catch that particular exception, not a general Exception , that is, if you expect an InvalidPersonException, which you should prefer:

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

to

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

Good luck

+123
Nov 08 '09 at 17:25
source share

The first saves the stack trace, and the second resets it. This means that if you use the second approach, the exception stack trace will always start with this method, and you will lose the original exception trace, which can be disastrous for those who read the exception logs, since it will never know the original cause of the exception.

The second approach can be useful if you want to add additional information to the stack trace, but it is used as follows:

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

There, the blog post discusses the differences.

+27
Nov 08 '09 at 17:20
source share

You have to use

 try { } catch(Exception e) { throw } 

if you want to do something with an exception before re-throwing (e.g. logging). A single roll saves the stack trace.

+6
Nov 08 '09 at 17:21
source share

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

The difference between throw; and throw e; The first one is used to re-throw exceptions, and the second is used to create a newly created exception. If you use the second option to restore an exception, it will consider it as a new exception and replaces all the information about the stack from where it was originally selected.

So you have not used any of the alternatives in the question. You should not use capture without parameters, and you should use throw; to restore the exception.

In addition, 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 expect.

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

If you want to add some information when you re-create an exception, you create a new exception with the original exception as an internal exception to save all the information:

 try { ... } catch (IOException e) { ... throw new ApplicationException("Some informative error message", e); } 
+4
Nov 08 '09 at 17:50
source share