Everywhere a single Catch block used catching top Exception all times.
-
I concur. Further, once the exception has been handled there should (normally) be no need to rethrow it. This rule leads to the useful guidline: catch exceptions at the lowest level where they can be meaningfully (i.e. completely) handled. The exception to the no-need-to-rethrow rule is when some cleanup action is needed as the stack is unwound. In that case, catch the specific type of exception, do the local cleanup only, and rethrow (ideally, using
throw
without a paramter - to preserve the stack trace). Do not duplicate the work that will be done in the can-meaningfully-handle-it catch block (such as logging, notifying the user, clearing context). Note that theusing (...){...}
construct implicitly follows this rule: in the event that the contained block of code throws an exception, it will automatically invoke the Dispose() method on the item allocated by the using() statement.Yes, I always liked C++'s RAII (Resource Acquisition Is Initialization) approach for exactly this reason. Every scope in C++ acts as an implicit "using" for all names declared within it, and the destructor is implicitly called when the scope exits. This gives deterministic resource management, but does leave more room for developer mistakes than managed languages. While "using" does allow this (to a degree) in C#, to apply it to every resource would sometimes result in a cascade of nested "using" blocks. In C++, its all automatic. Personally, I like to think I don't need my hands held by the compiler all the time.
"If you don't fail at least 90 percent of the time, you're not aiming high enough." Alan Kay.