I'm refactoring a medium-sized WinForms application written by other developers and almost every method of every class is surrounded by a try-catch
block. 99% of the time these catch blocks only log exceptions or cleanup resources and return error status.
I think it is obvious that this application lacks proper exception-handling mechanism and I'm planning to remove most try-catch blocks.
Is there any downside of doing so? How would you do this? I'm planning to:
To log exceptions appropriately and prevent them from propagating to the user, have an
Application.ThreadException
handlerFor cases where there's a resource that needs cleanup, leave the try-catch block as it is
Update: Using using
or try-finally
blocks is a better way. Thanks for the responses.
- In methods that "return-false-on-error", let the exception propagate and catch it in the caller instead
Any corrections/suggestions are welcome.
Edit: In the 3rd item, with "return-false-on-error" I meant methods like this:
bool MethodThatDoesSomething() {
try {
DoSomething(); // might throw IOException
} catch(Exception e) {
return false;
}
}
I'd like to rewrite this as:
void MethodThatDoesSomething() {
DoSomething(); // might throw IOException
}
// try-catch in the caller instead of checking MethodThatDoesSomething's return value
try {
MethodThatDoesSomething()
} catch(IOException e) {
HandleException(e);
}
"To log exceptions appropriately and prevent them from propagating to the user, have an Application.ThreadException handler"
Would you then be able to tell the user what happened? Would all exceptions end up there?
"For cases where there's a resource that needs cleanup, leave the try-catch block as it is"
You can use
try-finally
blocks as well if you wish to let the exception be handled elsewhere. Also consider using theusing
keyword onIDisposable
resources."In methods that "return-false-on-error", let the exception propagate and catch it in the caller instead"
It depends on the method. Exceptions should occur only in exceptional situations. A
FileNotFoundException
is just weird for theFileExists()
method to throw, but perfectly legal to be thrown byOpenFile()
.I think your strategy of removing try/catch block which just appear to do generic thoughtless logging is fine. Obviously leaving the cleanup code is necessary. However, I think more clarification is needed for your third point.
Return false on error methods are usually OK for things where exceptions are unavoidable, like a file operation in your example. Whereas I can see the benefit of removing exception handling code where it's just been put in thoughtlessly, I would consider carefully what benefit you get by pushing responsibility for handling an exception of this kind higher up in the call chain.
If the method is doing something very specific (it's not generic framework code), and you know which callers are using it, then I'd let it swallow the exception, leaving the callers free of exception handling duties. However, if it's something more generic and maybe more of a framework method, where you're not sure what code will be calling the method, I'd maybe let the exception propagate.