I've gotten in the habit of using a general catch statement and I handle those exceptions in a general manner. Is this bad practice? If so, how do I know which specific exceptions could be thrown and which ones do I catch?
The methods you run will generally show what exceptions can be thrown. You can then catch accordingly.
If it's your own code, you can generally see what will be thrown, or use the underlying classes exceptions as a guide on what you will need to catch.
I recommend a few links:
When using framework methods, you can check the MSDN documentation. Each method description has a list of potentially thrown exceptions.
As an example, check the Exceptions paragraph on File.Open() documentation.
When using your own method, you should be aware of exceptions potentially thrown by your methods.
Yes, except in a couple of very specific cases that's bad practice. The one common case I can think of where catching all exceptions isn't a lousy idea is when you're logging a message or a stack trace just before the app is about to tear itself down (or, maybe, you're logging and rethrowing).
Catch only the exceptions you know you can handle. No more, no less. If you don't know an exception can be thrown from a method, you aren't going to handle it properly anyway so don't catch it. Methods and libraries are responsible for documenting exceptions that you should be able to handle. Also, don't catch exceptions that indicate a logic failure, such as
NullReferenceException
andArgumentException
. These indicate a genuine bug in your software that you should fix, not something that you should handle at runtime.
The bigger question is if you need to do specific error handling on specific exceptions. If you just need to catch any errors that occur, there is nothing wrong with just making a generic try/catch block:
try
{
// Some Code
}
catch
{
}
However, if you need do specific handling on certain exceptions, you can specify multiple catch blocks per a single try:
try
{
// Some Code
}
catch(ArgumentException argE)
{
}
catch(NullReferenceException nullE)
{
}
catch(Exception e)
{
// Everything else
}
If you can't recover from an exception, don't catch it at that level.
Yes, that is bad practice. Rule of thumb: "catch the exceptions you are in a position to respond to, let the other ones go."
try {
File.Open(usersChosenFile, FileMode.Open);
} catch(FileNotFoundException) {
// tell the user the file is gone, give them a chance to respond
// this is good
} catch(UnauthorizedAccessException) {
// this is good too
} catch(Exception) {
// what did you just catch? Who knows. What if its OutOfMemoryException?
// Do you really want to deal with that here? Let this one go by
}
IMO - don't catch any exception unless you plan to add value to it and/or it can be handled in that method only.
Please do have a common exception handler which handles all un-handled exceptions.
HTH.
As Kyle said, make your methods small in length, put try/catch around small areas only. Hover the mouse over the methods that you call - you should get a list of exceptions then.
This will not catch every exception listed, but Exceptions can also be discovered empirically if you print the exception type inside of your catch (Exception e) { ... }
. What you are after is e.GetType().FullName
and e.StackTrace
and e.Message
and e.InnerException
... or a subset of what I listed.
Documentation will often describe what exceptions a method might throw and the conditions under which that might happen. This is especially the case with Microsoft's reference documentation for the .NET framework.
In my view, exceptions should only be caught if you have a good reason to catch them. This usually means that catching and handling them in a generic manner is unnecessary. Logging exceptions (a very common activity in an exception handler) should only happen at the bottom of the call stack or whenever you don't rethrow the (possibly wrapped) exception , which should be rare. If you have some action you want to take place at every frame in the call stack when an exception is bubbling down, take a look at Aspect Oriented Programming (AOP) techniques.
Except in rare situations, I generally think of catch blocks as a code smell.
Prevent exceptions being thrown at all by checking for conditions beforehand. For example, if reading from a file, use classes in System.IO to check if the file exists, rather than using a catch block to handle the situation where the file doesn't exist.
Catch blocks should not form part of your application logic.
You should catch those exceptions for which you can develop a reasonable strategy to deal with the problem. There's no point in catching an exception if there's no reasonable alternative (trying again later, using a different technology/technique to achieve the same overall goal, informing the user that the goal cannot currently be achieved and what they can do to remedy the situation).
Exception (pardon): It is worth having something at the very top level (e.g. Application.ThreadException or AppDOmain.UnhandledException) to attempt to log those exceptions that you haven't handled. If logging fails, you're doomed anyway.
But blindly swallowing all exceptions (especially at a low level) can lead to very frustrating debugging/diagnostic sessions.
You must make a design decision as to whether you really need to catch all exceptions at that point in code. I know of two conditions where catching Exception
makes sense:
- If you absolutely cannot allow an exception to bubble up and terminate your application.
- The calling code expect an exception to be thrown by your method/property because it is an atomic transaction. In which case, you catch all exceptions and return safely.
The downside of catching all exceptions is masking a potentially useful error message and disregarding it, causing unexpected side effects in your application.