Switch Statement – Handling Unreachable Default Case

enummaintenanceunit testing

If I'm using a switch statement to handle values from an enum (which is owned by my class) and I have a case for each possible value – is it worth adding code to handle the "default" case?

enum MyEnum
{
    MyFoo,
    MyBar,
    MyBat
}

MyEnum myEnum = GetMyEnum();
switch (myEnum)
{
    case MyFoo:
        DoFoo();
        break;
    case MyBar:
        DoBar();
        break;
    case MyBat:
        DoBat();
        break;
    default:
        Log("Unexpected value");
        throw new ArgumentException() 
}

I don't think it is because this code can never be reached (even with unit tests).
My co-worker disagrees and thinks this protects us against unexpected behavior caused by new values being added to MyEnum.

What say you, community?

Best Answer

Including the default case doesn't change the way your code works, but it does make your code more maintainable. By making the code break in an obvious way (log a message and throw an exception), you're including a big red arrow for the intern that your company hires next summer to add a couple features. The arrow says: "Hey, you! Yes, I'm talking to YOU! If you're going to add another value to the enum, you'd better add a case here too." That extra effort might add a few bytes to the compiled program, which is something to consider. But it'll also save someone (maybe even the future you) somewhere between an hour and a day of unproductive head-scratching.


Update: The situation described above, i.e. protecting against values added to an enumeration at some later time, can also be caught by the compiler. Clang (and gcc, I think) will by default issue a warning if you switch on an enumerated type but don't have a case that covers every possible value in the enumeration. So, for example, if you remove the default case from your switch and add a new value MyBaz to the enumeration, you'll get a warning that says:

Enumeration value 'MyBaz' not handled in switch

Letting the compiler detect uncovered cases is that it largely eliminates the need for that unreachable default case that inspired your question in the first place.