The switch statement
In the previous lesson, an if and else if chain picked a branch by its conditions. Often those conditions look alike: the same variable is compared with different values.
Picture an elevator in an office building. Its panel has one button per floor: the lobby is on the first floor, the cafe on the third, offices on the rest. You press "3", and the elevator goes straight to the third floor without stopping at every floor to ask whether it is yours.
An else if chain is like an elevator that does stop at every floor: it compares the same variable again and again. The switch statement works like the elevator's panel: it computes the value once and jumps to the branch with the same value.
int floor = 3;
switch (floor)
{
case 1:
Console.WriteLine("Lobby");
break;
case 3:
Console.WriteLine("Cafe"); // Cafe
break;
default:
Console.WriteLine("Offices");
break;
}The lines case 1:, case 3: and default: are called labels: each marks where its branch begins.
Let's go through the program:
switch (floor)computesfloorand gets3.- The label
case 1:does not match3, and its code does not run. - The label
case 3:matches, so the code under it runs: the program printsCafe. breakends theswitch, and the program moves on to the code after the closing brace.
With floor = 1, the program prints Lobby, and any number other than 1 and 3 gives Offices.
The case and default labels
The code under a label is called a branch, as in if. A switch has two kinds of labels.
The case label
The word case is followed by a value and a colon, and the branch's code goes below. A case label checks whether the value in the switch parentheses equals its own value.
The value after case must be known at compile time: a number, a character, a string in quotes, or a constant declared with const. The compiler does not accept an ordinary variable there. Two case labels with the same value do not compile either.
The default label
The default branch runs when no case matches, like else in an if chain. It usually goes last.
If no case matches and there is no default branch, nothing runs. The program moves on to the code after the switch's closing brace.
A branch must end
In C#, every branch must leave the switch, and in this theme that is what break does. Execution cannot flow from one branch into the next: if a branch ends without break, the program does not compile. The rule covers the last branch too, even default.
Interviewers like to ask about this. In C, C++ and Java, a branch without break silently continues into the next branch's code, and a forgotten break becomes a bug that is hard to find. C# forbids that, so the compiler finds a forgotten break.
Several labels on one branch
The rule has one allowance, though. If a label has no statements under it, it belongs to the branch below. That way several values share the same code:
int day = 6;
switch (day)
{
case 6:
case 7:
Console.WriteLine("weekend"); // weekend
break;
default:
Console.WriteLine("workday");
break;
}Let's see what happens:
dayis6, and execution starts at the labelcase 6:.- There are no statements under it: the labels
case 6:andcase 7:sit above one branch. - The program prints
weekend, andbreakends theswitch.
This is where the elevator analogy breaks down. An elevator button stands for one floor, but a switch branch can have several labels, and all of them lead to the same place.
switch on a string
The value in a switch can be a string, not only a number. Then the case labels hold strings in quotes:
string command = "stop";
switch (command)
{
case "start":
Console.WriteLine("Starting");
break;
case "stop":
Console.WriteLine("Stopping"); // Stopping
break;
default:
Console.WriteLine("Unknown command");
break;
}Strings are compared whole and case-sensitively. If command holds "Stop" with a capital letter, no case matches, and the program prints Unknown command.
Common mistake
A branch is missing its break:
int level = 1;
switch (level)
{
case 1:
Console.WriteLine("beginner"); // ✗
case 2:
Console.WriteLine("advanced");
break;
}error CS0163: Control cannot fall through from one case label ('case 1:') to anotherThe program does not compile. The message means that execution cannot pass from one case label to another. The case 1: branch ends without break, and the compiler does not let it continue into the code of the case 2: branch. To make the program compile, add break after Console.WriteLine("beginner").
Key points
switchcomputes the value once and runs the branch with the matchingcase, or thedefaultbranch if there is none.- A
caselabel holds a value known at compile time: a number, a character, a string or aconstconstant. - Every branch ends with
break: without it, the program does not compile. - Several labels in a row with no statements between them lead to one branch.