Why don't we have an "UnreachableCodeException"?

Continuing my, apparently, semi-regular series of gripes about missing features in programming languages:

Modern languages support many exception types. For example, here is a partial list of all the exception types natively available in C#. Many of these types are useful! And of course we can always user-define our own exception types if necessary.

But once again, there's something I'd rather not have to user-define, because it would be cool if the language natively supported it.

Here's a common pattern. Let's say we have an enum:

enum AccountType
{
    Personal,
    Educational,
    Commercial
}

And somewhere, we have a switch statement that handles all values of the enum:

switch(accountType)
{
    case Personal:
        //do personal stuff
        break;
    case Educational:
        //do school stuff
        break;
  case Commercial:
        //do business stuff
        break;
}

Most compilers and/or linters will yell at us for not including a default: statement here. Which is fair; default behavior is a good thing to have. But in this case, we have already exhaustively handled all the possible values of accountType! The only way we would ever need this default statement would be if someone added a new type of account without updating the switch statement, or removed a case from the switch statement.

This is where it would be nice to have an UnreachableCodeException. In a use case like this, you would use it like so:

switch(accountType)
{
    case Personal:
        //do personal stuff
        break;
    case Educational:
        //do school stuff
        break;
  case Commercial:
        //do business stuff
        break;
  default:
        throw new UnreachableCodeException($"Unexpected AccountType value encountered: {accountType}");
}

For a more general description, the UnreachableCodeException should be used to mark code paths that the compiler thinks are valid, but that should not ever be accessed. Like above, adding them to defaults in switch statements that already cover all known values is one common scenario, but there are others - for example, if you're bounds-checking a value that should not be possible to go out of bounds, or if you have to end a method body having already returned for any possible scenario it might encounter.

The closest thing C# has to this, that I can think of, is the NotImplementedException which is available for a similar use case - marking code paths that should not be called. But in that case, there's a subtle difference of idiom--it's for either stubbing out code paths that are not implemented yet, but will be, so your code can compile until you get there, or for marking code paths that have to be implemented but should never be called, for example if you're mocking out an interface that only needs some of its methods.

I would argue that the difference here is enough to call for a new exception type. Someone should make it happen! Meanwhile here's a user-defined way to make it work, if you want:

[Serializable()]
public class UnreachableCodeException : System.Exception
{
public UnreachableCodeException() : base() { }

public UnreachableCodeException(string message) : base(message) { }

public UnreachableCodeException(string message, System.Exception inner) : base(message, inner) { }

protected UnreachableCodeException(SerializationInfo info, StreamingContext context) { }
}

You'll only receive email when they publish something new.

More from Tom
All posts