The Great Debate: Always Include a Default Case in Switch?


A switch statement is often used in programming to check a condition against a set of possible values or cases. Whether it is mandatory to use its default case has sparked some debate among programmers over the years.

It is not mandatory to include a default case in the switch statement. But, there are four reasons why it’s beneficial to do so:

  1. To ensure that all possible cases are covered,
  2. To provide a catch-all for unexpected input,
  3. To handle the default actions or special behaviors,
  4. To improve readability.

This article explains why a default case clause should always be there and on which occasions it is okay to avoid it.

 Should switch statements always contain a default clause?

As stated above, it is not mandatory to declare the default clause in a switch statement. It is entirely optional. Without it, the code will still be valid.

However, as a good programming practice, you should always declare a default clause in the switch expression.

Let’s dive deeper into why you might include a default case, well, by default.

Default case ensures that all possible cases are covered

One of the most important reasons to declare default cases is to ensure your program covers all the possible cases.

Refer to the following C# code example. Here, the switch statement evaluates if a variable matches numbers 1, 2, and 3, and the program executes specific functions before the break statement.

There are many possibilities for the switch variable number.

public class SwitchExample1
{
    public static void CheckValue(int number)
    {
        switch (number)
        {
            case 1:
                Console.WriteLine("case value 1: " + number);
                //function 1
                break;
            case 2:
                Console.WriteLine("case value 2: " + number);
                //function 2
                break;
            case 3:
                Console.WriteLine("case value 3: " + number);
                //function 3
                break;
        }
        //rest of the code goes here
    }
}

One example of usage:

SwitchExample1.CheckValue(3);

Unless your program guarantees that there will be no numbers other than 1, 2, and 3, you should not ignore all other possibilities here. That’s because without silently ignoring the other values, providing a default behavior for all other possible cases in your code provides you with a better and more user-friendly application.

If you take the second example below, the grade parameter can only have 26 possibilities. Of course, if we include the letters of the English alphabet and ignore other characters. The grade should only be either A, B, or C. The program shows an invalid message to the user covering the rest of all the possible characters.

public void DisplayGradeMessage(char grade)
{
    switch (grade)
    {
        case 'A':
            Console.WriteLine("A high performer ");
            break;
        case 'B':
            Console.WriteLine("Average performer");
            break;
        case 'C':
            Console.WriteLine("Weak performer");
            break;
        default:
            Console.WriteLine("Invalid grade!");
            break;
    }
}

Default case provides a catch-all for unexpected input

The second reason you should use a default case is to provide error handling for unexpected input. Your program may never reach the default statement.

However, there can be invalid cases. If you never track such cases, there can be possibilities like data corruption, incomplete validations, unauthorized access, etc. In such cases, the default statements should contain some form of error handling. 

For example, the following method ReadTheFile checks the systemUserID variable and does the user-specific file read operation before the break statement. Suppose the systemUserID is a value other than those two permitted users.

public class DefaultCaseErrorHandling
{
    public static void ReadTheFile(string systemUserID, string fileName)
    {
        try
        {
            switch (systemUserID)
            {
                case "LS":
                    Console.WriteLine(" LS user ");
                    //LS user-specific read operation 
                    break;
                case "CG":
                    Console.WriteLine("CG user");
                    //CG user-specific read operation
                    break;
                default:
                    throw new UnauthorizedAccessException();
                    break;
            }
        }
        catch (Exception e)
        {
            Console.WriteLine(e);
        }
        //rest of the logic goes here
    }
}

When you call the method with the following parameters:

DefaultCaseErrorHandling.ReadTheFile("BS", "fileName");

the program warns the application that an unauthorized user has tried to read the file without permission.

System.UnauthorizedAccessException: Attempted to perform an unauthorized operation.

Default case handles the default actions or special behaviors

You can use the default case to handle default actions of special behaviors.

Assume you have a menu that gets the user input and does specific tasks based on the menu number. There are three menu items. After each three menu functions, the program needs to return to the main menu. The program should exit without returning to the menu if the user selects a number other than 1, 2, or 3.

To achieve that functionality, you can use a variable to check whether to continue or not and set it to false in the default case to exit the program without showing the menu.

static void Main(string[] args)
{
    bool continues = true;
    while (continues)
    {
        Console.WriteLine("1. View balance \n");
        Console.WriteLine("2. View account details\n");
        Console.WriteLine("3. View last transaction\n");
        string menuNumber = Console.ReadLine();

        switch (menuNumber)
        {
            case "1":
                Console.WriteLine("your balance: ");
                break;
            case "2":
                Console.WriteLine("your account details");
                break;
            case "3":
                Console.WriteLine("the last transaction");
                break;
            default:
                Console.WriteLine("Exiting from the main menu…");
                continues = false;
                break;
        }
    }
    Console.WriteLine("Proceed with next operation.");
    //rest of the logic goes here
}

Including default case block improves readability

Having a default case shows you that you have considered every possibility in your program. If there is nothing to handle in the default case, you can add a comment line in the default case stating that no logic is needed (check the following example).

Future programmers who refer to your code know why the default case is not required and why the switch variable can only have those cases, thereby improving the code readability.

Are there any exceptions to the rule?

If the switch variable only contains specific obvious values, it is okay to ignore the default case. For example, in the following switch statement, the switch variable is a switch that can only have either 0 or 1.

var isEnabled = GetSwitchValueFromConfig();

switch (isEnabled)
{
    case 1:
        DoSomething();
        break;
    case 0:
        DoSomethingElse();
        break;
    default:
        // not required as this is a switch
        break;
}

Also, think you are checking for days of the week declared an Enum, an enumerated type.

Then obviously, you can have only seven different values. Another example is checking for keystrokes which can have four values; move up, down, left, and right. Therefore, the default case is not required to define in such cases.

However, as explained above, to enhance the code readability, you should always declare the default statement and add a comment explaining why you have not considered the default case there.

Conclusion

A switch statement is a must-have structure to evaluate conditions with multiple cases. It is not mandatory to define its default block.

However, there are several reasons why it should always contain the default code block. By defining it, you can ensure you have covered every possibility, provided error handling, and covered edge cases. But, most importantly, you improve the code readability.

If it is evident that the switch block can only contain a specific value, then it is okay to ignore the default case.

Recent Posts