3

What's the difference between using

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

and using

catch   //  might include  (Exception) 
{
   ...
   throw;
}
jmayor
  • 2,725
  • 4
  • 29
  • 37

5 Answers5

12

throw ex re-throws the exception object from that point. This is generally bad, since it destroys the useful call stack information which lead up to the original problem.

throw releases the original caught exception, from the point it was actually thrown. It retains the call stack information up to that point, instead of to the point you caught.

catch(Exception) and catch are essentially the same thing, except obviously the first gives you the exception object to do something with, and the second does not. But both will catch all exceptions. They are distinct from catch(SomeKindOfException), which will only catch exceptions of that specific type (or more specific types derived from that type). This is best for situations like:

try
{
    //some file operation
}
catch(FileNotFoundException fnfex)
{
    //file not found - we know how to handle this
}
//any other kind of exception,
//which we did not expect and can't know how to handle,
//will not be caught and throw normally
Rex M
  • 142,167
  • 33
  • 283
  • 313
  • Additionally, catch(Exception) limits the scope of what can be caught. plain catch will catch absolutely anything that is thrown, essentially the same as catch(object) – Erich Oct 31 '09 at 20:02
  • Thanks... mainly the information about the call Stack was my doubt, but everything is really usefull – jmayor Oct 31 '09 at 20:03
  • @Erich have you ever thrown something which did not derive from Exception? – Rex M Oct 31 '09 at 20:04
  • I have not, though it is a difference, and he asked for the differences. To be terribly honest, I'm quite sure it is impossible to THROW something that doesn't derive from exception, so I don't know why the language is designed this way. – Erich Oct 31 '09 at 20:09
  • @Rex: If you check my comment on my post below, apparently this was something that only meant something back in 1.1. Since 2.0, non CLS exceptions are wrapped in an Exception type, however previously they weren't necessarily wrapped. So apparently the empty catch DID actually do something meaningful at one point. – Erich Oct 31 '09 at 20:20
4

Using catch without a parameter was useful in framework 1.x to catch exceptions thrown from unmanaged code. From framework version 2 (IIRC) all unmanaged exceptions are wrapped in a managed Exception object, so there is no use for the parameterless catch any more.

The parameterless throw is not specific for the parameterless catch, it can be used in any catch block. The difference is that when retrowing an exception using throw; it doesn't overwrite the stack trace from when the exception was originally thrown, so that is the correct way of rethrowing an exception.

Instead of using throw ex; in a catch block you should throw a newly created exception containing the information that you want to add, with the original exception as the inner exception. That way you get both the original point of failure, and the point where you caught it and rethrew it.

So, you should never use either of the combinations in the examples in your question. You always specify the exception type, and you either just retrow the exception:

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

or you throw a new exception with an inner exception:

catch (Exception ex) {
   ...
   throw new ApplicationException("Ooops!", ex);
}

Note that you should rarely catch the Exception base class, but a more specific exception class that is appropriate for the error that you anticipate. There is usually no point in catching an exception that you don't know how to handle.

Guffa
  • 687,336
  • 108
  • 737
  • 1,005
  • I hate to disagree, but I still find the parameterless catch useful. I do program with Lotus Notes and it is fond of throwing exceptions at me for flow control. Since I can't seem to find a listing of all the exceptions it throws, I have to use the parameterless catch to prevent the component from failing and destroying the whole app. – jasonh Oct 31 '09 at 20:08
  • @jasonh: Flow control seem to be an odd reason for throwing exceptions... Anyhow, unmanaged exception that can't be mapped to managed exceptions are transformed to the COMException class. As a last resort you can catch the base class Exception, that's better than a parameterless catch as it gives you some little information about the error. – Guffa Oct 31 '09 at 20:21
  • But isn't catching an Exception the same as catching everything? i thought if you threw a non-Exception type it was wrapped in one before it's actually thrown... – RCIX Nov 03 '09 at 02:39
  • @RCIX: The difference is that when catching Exception you get a reference to the Exception object and when you use a parameterless exception you get no information at all about the exception. – Guffa Nov 03 '09 at 06:07
1

Well, the first one will erase the stack trace, and replace it with where your throw is. The second one will throw the exception without altering the stack trace.

Also, "catch" will catch ANYTHING that is thrown, whether it is an exception or not.

The 2nd one is actually the equivalent of doing "catch(object)".

Erich
  • 657
  • 5
  • 6
  • (Not my downvote) Anything in .NET is an object; even a "throw 1" would be caught by "catch(object)" – Andomar Oct 31 '09 at 20:01
  • Exactly my point! catch(Exception) would miss a 'throw 1' or a 'throw "blah"'. – Erich Oct 31 '09 at 20:02
  • Perhaps true in theory, but have you ever thrown or caught 1? – Rex M Oct 31 '09 at 20:05
  • Well I wasn't the one that vote you down, I think I can't tell who did it. But I think it was because of the catch(object) , in basically any Class you want to put inside the catch mush extend System.Exception – jmayor Oct 31 '09 at 20:06
  • Haha, looks like you can't actually throw a 1; that must be a memory from C++. Thanks Rex M – Andomar Oct 31 '09 at 20:07
  • It is impossible to throw or catch something not deriving from System.Exception. Compiler error CS0155 – Marcel Gosselin Oct 31 '09 at 20:08
  • @jmayor: That is correct, I didn't think I passed that off as valid code, I mentioned that a plain catch was the equivalent of that pseudo code. In addition, even the 'throw 1' is not valid code, so I don't know why a blank catch is a 'catch object'. As for the downvote: I included more differences than the accepted answer, included the answer Rex gave, and even beat him by more than 10 seconds, so I still don't understand the downvote. – Erich Oct 31 '09 at 20:11
  • It gets weirder: apparently in VB.Net, catch(Exception) and catch are identical. According to the CLR team blogs (http://msdn.microsoft.com/en-us/library/ms229005.aspx and http://blogs.msdn.com/clrteam/archive/2009/02/19/why-catch-exception-empty-catch-is-bad.aspx), an empty catch will catch "Non CLS Exceptions". Apparently, in .Net 1.1, non-CLS exceptions thrown from used libraries (COM and stuff?) were not automatically wrapped. – Erich Oct 31 '09 at 20:19
  • +1 to offset the downvote presumably because of your catch(object) claim...which, by the way, is 100% correct. That is, in fact, exactly what the C# compiler does. – Brian Gideon Oct 31 '09 at 23:40
0

The first one resets the stack trace property in the thrown exception

Matt Breckon
  • 3,374
  • 20
  • 26
-1

As far as I know, it's the same thing (using Exception.. because all the exceptions derive from that class). It becomes different when you catch only a child of Exception... or when you have several "catch" catching different children. It could also be that you catch Exception, modify the message, and throw it back out.

Nestor
  • 13,706
  • 11
  • 78
  • 119