Switch statements have a venerable history in programming languages. They were introduced in C
where they were prized for their speed. That speed came at the cost of functionality which was very constrained. In C# the role of the switch statement has been expanded beyond integers. Switch statements can encompass any arbitrary type, value or reference.
If you are coming from a functional language then working with switch statements (and switch expressions discussed elsewhere) is the nearest you will get in C# to using discriminated unions and pattern matching. However, they have nowhere near the discriminated union's power to enforce type safety.
Simple switch statements resemble their C
ancestors combining switch
, case
, break
and default
.
int direction = GetDirection();
switch (direction)
{
case 1:
GoLeft();
break;
case 2:
GoRight();
break;
default:
MarkTime();
break;
}
The above pattern can be used with any simple (primitives + strings) type.
When reference types are added into the mix then extra syntax is involved, firstly to down cast the type and then to add guards (when
) although guards can be used with simple value cases. This is illustrated below:
Animal animal = GetAnimal();
switch(animal)
{
case Dog canine:
case Coyote canine:
canine.Bark();
break;
case Cat cat when cat.HasOnly8Lives():
cat.IsCareful();
cat.Meow();
break;
case Cat cat:
cat.Meow();
break;
}
default
clause is optional but typically desirable.break
statement is mandatory for any non-empty case
clause.case
labels must be derived from the type of the switch
argument. A switch
argument of type Object
obviously allows the widest range.case
argument.case
with different case
arguments can refer to the same code block.switch statement documentation provides an introduction to switch
statements.