Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Do I need a "Default" statement in this scenario?

Often in school, our lecturers will tell us to always include a Default statement at the end of a switch case statement. However, I have always been wondering is it necessary for ALL (or most) scenario?

Consider the following example in C++:

int num = rand()%3;
switch (num)
{
   case 0: methodOne();
           break;
   case 1: methodTwo();
           break;
   case 2: methodThree();
           break;
}

In the case above, I feel that it is impossible to have a case where it can be > 2 or < 0, so do I still need to include a Default statement?

There are similar questions in SO asking for the need of Default in switch-case. The replies given there stated that we should almost at anytime include a Default. But of all the cases I encountered personally, it just seems to be redundant since the Default can never be reached.

Edit: Also, in terms of defensive programming, does this scenario needs a Default statement? And if I were to add a Default statement. It will only be a error-handling statement, am I right to say that?

like image 362
user3437460 Avatar asked Dec 06 '22 02:12

user3437460


1 Answers

Technically, no you don't, because you've covered all possible cases with your switch statement.

However, I always find it useful to include an assertion/exception in the default anyway. Consider the following scenario:

// V1.0.0: Initial version.
int num = rand()%3;
switch (num)
{
   case 0: methodOne();
           break;
   case 1: methodTwo();
           break;
   case 2: methodThree();
           break;
}

Later...

// V1.0.0: Initial version.
// V1.0.1: Added a fourth method.
int num = rand()%4;
switch (num)
{
   case 0: methodOne();
           break;
   case 1: methodTwo();
           break;
   case 2: methodThree();
           break;
}

In this scenario, developer #2 updated the rand modulus, but didn't actually add the case to handle num == 4. Without the default, you're going to silently fail, and that could cause all kinds of badness that could be very hard to debug. A more maintainable solution might be:

// V1.0.0: Initial version.
// V1.0.1: Added a fourth method.
int num = rand()%4;
switch (num)
{
   case 0: methodOne();
           break;
   case 1: methodTwo();
           break;
   case 2: methodThree();
           break;
   default:
           assert(false);
           throw InvalidNumException("BUG: Method has not been specified for value of num");
}

When debugging, this would stop the debugger at the assert, and if (god forbid) the missing case makes it all the way to production, you'll get an exception thrown, rather than just running off and doing stuff that shouldn't happen.

EDIT:

I think including a catch-all is a good addition to a defensive programming style. It guarantees that you'll get a useful outcome if you miss a case statement (even if that useful outcome is to cause the program to crash).

EDIT 2:

As Andre Kostur mentioned in a comment to this answer, some compilers will emit warnings if you switch on an enum and forget to handle a case, which is a good reason to not include a default case for an enum switch statement. Refer to Phresnel's answer for more information about that.

like image 65
Karl Nicoll Avatar answered Dec 08 '22 16:12

Karl Nicoll