Please consider the following piece of code, which throws three different exceptions (namely, System.Configuration.ConfigurationErrorsException
, System.FormatException
and System.OverflowException
):
int SomeInt = Convert.ToInt32(ConfigurationManager.AppSettings["SomeIntValue"]);
The exceptions are different, and so in practice I should have three different catch
blocks to handle each particular exception. However, in this particular case, all exceptions are handled the same way: a log is written to, say, EventViewer, and a message informing of a configuration error is displayed... In this particular cause, is it too bad to use
try
{
int SomeInt = ConfigurationManager.AppSettings["SomeIntValue"];
}
catch (Exception ThisException)
{
/* Log and display error message. */
}
or should I, instead, use the three catch
blocks and repeat the code within each of them?
Also when you catch all exceptions, you may get an exception that cannot deal with and prevent code that is upper in the stack to handle it properly. The general principal is to catch the most specific type you can. catch(Exception) is a bad practice because it catches all RuntimeException (unchecked exception) too.
As others have said, as a general rule, you should catch an exception when you can actually handle it, otherwise, just throw it.
Catching generic exceptions is only a good practice when doing an exception hierarchy that is expected catch everything except errors. For example, going from the most specific exceptions to less specific, and finally Exception.
Catching Throwable will catch all Error s and Exception s. This is very bad since errors are thrown by the JVM only if the application encounters a serious condition such as StackOverflowError or OutOfMemoryError and they are never meant to be handled.
What is really needed, but the .net exception hierarchy doesn't provide, is a clean way of distinguishing exceptions which mean "The requested operation didn't happen, but the system state is essentially fine except to the extent implied by the operation not having happened" from those which mean "The CPU is on fire, and even trying to save the current user's work would likely as not make things worse." There are a lot of contexts in which one really should endeavor to catch all exceptions of the first type, while ideally not catching those of the second. While there a few gradations beyond the two above, generally when catching exceptions one doesn't really care about the distinction between an InvalidArgumentException or an InvalidOperationException; what one cares about is whether the overall system state is valid or corrupted.
As it is, if one is making a call to e.g. a file-import plug-in and it throws an exception, I'm not really sure one can do except try to catch and rethrow really bad exceptions, while having all other exceptions put up a "This file could not be opened" dialog box. Hopefully the state of the system at that point is essentially as it would be had the user not tried to open the file, but without some standardized way of indicating exception severity, I don't think there's any way to be sure.
Incidentally, if I had my druthers, there would be a class ExceptionBase, from which all exceptions would derive; most exceptions would derive from Exception (which would in turn derive from ExceptionBase) but things like ThreadAbortException, StackOverflowException, OutOfMemoryException, etc. would be derived from CriticalException. That way one could catch most 'unexpected' exceptions without accidentally stifling the really bad ones.
It is bad practice to catch System.Exception . . . or better yet, it is bad practice to handle System.Exception anywhere but the top level of your application. What you should to is:
Example code:
catch (Exception ex)
{
if (ex is FormatException || ex is OverflowException || ex is ConfigurationErrorsException) {
CommonHandler();
}
else {
throw;
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With