In C#, what is the difference Between \'Catch\', \'Catch (Exception)\', and \'Catch(Exception e)\' ?
The MSDN article on try-catch uses 2 of them in its examples, but do
In short...
Catch
without a parameter will receive any exception but provide no means to address it.
Catch (Exception)
will essentially do the same thing, because you've specified the root Exception
type. As opposed to Catch (IOException)
which would only catch the IOException
type.
Catch (Exception ex)
catches all exceptions and provides a means to address it via the ex
variable.
Read more: http://msdn.microsoft.com/en-us/library/ms173160.aspx
No one has yet mentioned the historical aspect of this question.
In .NET it is legal to throw an object that does not derive from Exception
. (It is not legal in C#, but it is in some other managed languages.) Many people are unaware of this fact, but it is legal. Since that is crazy, in .NET 2.0 the default was changed: if you attempt to throw something that is not an exception then it is automatically wrapped in the RuntimeWrappedException
class which obviously is an exception. That object is then thrown.
Because of this oddity, in C# 1.0 it was common to see code that did both:
try
{ do something }
catch(Exception)
{ handle the exception }
catch
{ handle the thrown non-exception }
And in fact there were security and correctness issues; there are situations in which for security reasons you must catch anything that is thrown (possibly to re-throw it) and people would think reasonably that catch(Exception)
caught everything, but it didn't.
Fortunately since .NET 2.0 things have been more sensible; you can rely on catch {}
, catch(Exception) {}
and catch(Exception ex) {}
to all catch everything should you need to.
And finally: if for some crazy reason you want to turn on the C# 1.0 behavior, you can put
[assembly:System.Runtime.CompilerServices.RuntimeCompatibility(WrapNonExceptionThrows = false)]
in your program.
First version catches all exceptions deriving from the Exception class.
The second version catches specified exception.
The third version catches a specified exception with a declared name. Then in the catch block you can use this object, for example, to see the complete error: e.ToString();
Read more here.
At the highest level they are all the same; they all catch exceptions.
But to drill down further, in the first case you are catching an exception and doing nothing with it (you don't have a defined type). In the second example, you are catching an exception of the Exception type. In your last example, you are catching the same Exception type as in example 2 but, now you are putting the exception into a variable that would allow you to show it in a MessageBox or:
e.Message
It's important to note as well that exceptions are tiered meaning, if you are catching multiple types of exceptions in the same try/catch block, you go from the most specific exception type to the most general. Like this:
try {
}
catch (SqlException sqlExc) {
}
catch (Exception exc) {
}
All of them do basically the same thing, the difference being the amount of information they provide about the error.
catch (foo ex) {}
will filter out all exceptions, except those that can be cast to type foo
. It also gives you the instance of the error for you to work on.
catch (foo) {}
does the same as above, but it doesn't give you the instance of the exception. You'll know the type of the exception, but won't be able to read information from it.
Notice that in both of those cases, if the type of the exception is Exception
, they'll catch all exceptions.
catch {}
catches all exceptions. You don't know the type it caught and you can't access the instance.
You can choose which one to use based on how much information you need from the exception should it be caught.
Regardless of which one you use, you can pass the caught exception forward by using the command throw;
(without arguments).
In your example, nothing, since you're not doing anything with the exception. But to clarify…
This catches everything but does nothing with the exception.
catch {}
This is only useful when you want to say guarantee a return from a method.
This catches only exceptions of type Exception
(which is everything) but does nothing with the exception.
catch (Exception) {}
This is useful if you wanted to limit the type of exception being caught by specifying which types you want to handle. Any other exceptions will bubble up the call stack until a proper handler is found.
This catches only exceptions of type Exception
(which is everything) and could do something with the exception, but happens to do nothing
catch (Exception ex) {}
This technique gives you a lot more options. You could log the exception, inspect the InnerException
, etc. And again you can specify which types of exceptions you wish to handle.
Unless you're re-throwing the exception somehow, all of these are bad practice. In general, you should only catch the exceptions you can meaningfully handle and allow anything else to bubble up.