8

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.

  • What you want is reuse the name but not the type. There is specific meaning attached to MissingMemberException. Simply define a new type that is specific to your framework and carries exactly the right meaning. – usr Aug 6 '15 at 20:41
7

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.

  • 2
    This is brilliant strategy when subclassing exceptions. I'm not sure if you are saying to subclass exceptions in every case or your are simply saying that when you sub-class this is how you should do it. In regards to if you should subclass I agree with the answer @DanielS posted. – Chuck Conway Aug 5 '15 at 0:50
3

The answer is of course "it depends," but given your use case, I would say no. Here's why:

C# is a wonderful - scratch that, the best - object-oriented language around. It is so good, in fact, that I will sometimes get caught up trying to implement a fanatically purist vision of what began as a simple project. That doesn't happen to me so much when writing JavaScript or Objective-C or PHP code.

When I get in this "mode," this sort of paralysis, one of the symptoms can be an obsession with exception handling and generics and meta-programming. Sometimes all three together. It is far more likely to be an issue when I am working on something new, relatively unknown, or with shoddy specifications and goals. Rather than bogging myself down in the implementation details, I think, why try to create something that can accommodate most of the scenarios I reasonably anticipate? Then, when I get around the getting the details, the foundation will be laid and I will write a bunch of stubby little methods, and so on. Maybe somebody else will work on the UI code, I'll just provide them these nice services and these contracts...

Unfortunately, that has yet to happen to me. What tends to happen is that I start down this path working on "infrastructure" - things like:

  • Writing my own IoC container interfaces or otherwise screwing around with Castle.Windsor
  • Determining how I am going to handle type mapping in the application
  • Writing control flow logic for abstract base classes that resemble Interceptors and wrapping calls to abstract members with exception handling
  • Creating abstract base classes for IRepository, IUnitOfWork, IDomainService, ICrossCuttingValidation, etc.
  • Trying to describe a hierarchical object model for something whose very nature denies such a meta- approach (like IFrameworkException)

When you get hung up on whether an exception's description is precise enough for your tastes, you are really denying some other critical feature from being implemented. The nature of the exception is also telling - it is not an event-driven exception, it occurs evidently far from any input methodology (like a UI or a pipe or something) and is probably deterministic in nature - as in, you can't predict what a user will input, but you can predict which assembly you choose to load or whatnot.

By the way, if the description bothers you so much, can't you write an extension method to override it in the appropriate scope?

So this is really just me kind of projecting my own over-abstraction and analysis paralysis onto you but I think it may be appropriate. I would say that to stay on the safe side, only subclass an Exception when:

  • You have actually experienced a runtime exception that you are seeking to handle in general
  • The runtime exception is not something that you could reasonably rule out at design time
  • The exception is not already well-covered by the huge existing number of Exception subclasses
  • You actually have an idea in mind of how you want to handle the exception OR if not, only because it is so complicated that you need to think about it and get back to it
  • Your idea goes beyond changing its metadata, its scope, its inner exception, etc, and deals more with the underlying object or event producing the exception and/or the means of actually dealing with it
  • You have already written or are not responsible for the majority of the input-facing side of things like the UI
  • I appreciate your pragmatic approach. As with everything it depends. – Chuck Conway Aug 5 '15 at 0:45
1

In my view custom exceptions make sense only in 2 cases:

1) you're developing an Api

2) you use it in your code to recover from a failure.

In any other scenario, built in exceptions should be sufficient.

In your case you could use InvalidArgumentException

  • You should expand your answer a bit and give a "Why" to each bullet-point. You are spot on here. Creating custom exceptions is yet another system/hierarchy to maintain. – Chuck Conway Aug 5 '15 at 0:42

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.