C# – Should I make the own exceptions, or co-opt similar exceptions for slightly non-standard purposes

cexceptionsnetobject-oriented

This is a general design question, but I'm focusing on C# and .NET because those are the languages I'm working with right now.

Should I create my own, new exception classes, or co-opt existing framework exceptions for slightly different purposes?

For example, I'm finding myself needing an exception that indicates a member (that is, of a type for example) was expected, but has not been found while reading an assembly using Mono.Cecil. The base class library defines the exception MissingMemberException, which seems to communicate exactly what I want, but the description says:

The exception that is thrown when there is an attempt to dynamically
access a class member that does not exist.

Which doesn't fit exactly, because I'm not dynamically accessing the member, but rather working with the assembly passively.

Best Answer

In general

Subclassing exceptions is a good idea to group the exceptions into the families or groupings that they belong to. It also allows client code the opportunity to handle exceptions based on specific errors or more generally. I usually divide the tree somewhere near the root between the logical and runtime errors (e.g. in C++ the std::runtime_error vs. std::logic_error).

Being able to differentiate between the system exceptions and your application's exceptions is also a good idea. It would be odd if the client code is watching for an system failure of some sort but catches your (via a base class) code's logical error.

Given this case and C#

C# has a rich and large exception hierarchy - I wouldn't try pick up a base class too deep into it. Following on your example, it sounds like your are throwing a logical error (or at least an application error), so the base class or even just that exception would hint at a system error. The exact exception can be debated, but I think in this case it is not a good choice.

Hierarchy

I would build a hierarchy that allows you to distinguish between system and application errors and then further between runtime and logical errors. Do not be afraid to use inner exceptions - catch the system error and wrap it in something more meaningful given the context in which it is being thrown. Don't go overboard, focus on what would be key exceptions. Exceptions can have unique textual descriptions associated with them - use them to give a user even more detail or hints at what to do to correct the problem.

Related Topic