Ideally, exceptions should be grouped in a hierarchy so that if the code handles several exceptions in the same way, they will all be derived from a common base class. If the base type, capable of throwing, was an interface, not a class, such an ideal might be somewhat achievable. However, the one-way restriction for classes severely limits the usefulness of the hierarchy.
The only time an exception hierarchy can be a useful concept is that implementing an interface or a new version of a class that is documented as throwing certain exceptions requires that the code be different from more different conditions than these exceptions. In such a scenario, an exception from the method of exceptions that is not the result of documented ones would be a violation of the changes, so you need to exclude the exception that inherits from the documented one that best describes the previously unforeseen condition. This is pretty ugly, but the exception handling mechanism doesn't really provide a better alternative. It’s very sad that things like IEnumerator<T>.MoveNext() are not documented as throwing any exceptions that would simply mean “Sorry - the system is not burning or something else, and I don’t know that anyone then changed the collection, but I can neither move on to the next item, nor honestly say that the transfer is completed, "but they do not.
Except when you need to create an exception that is compatible with existing code, it may be useful if the exceptions used by the application or library are derived from a common database. Instead of using ApplicationException it should be something like YourApplicationNameException or YourLibraryNameException - something from which nothing comes of it. Something like ApplicationException bad, because the code that catch ApplicationException will receive not only the exceptions it received from this type, but also any exceptions from which any other libraries are thrown.
source share