Published on

Switch Statements in C#: Evolution and Enhancements

Introduction

Switch statements have been a fundamental part of C# since its inception, providing a way to execute different blocks of code based on the value of a variable. This article explores the evolution of switch statements in C#, from their basic form before C# 7.0, through significant enhancements in C# 7.0, C# 8.0, and C# 9.0, culminating in the introduction of pattern matching in C# 9.0.

Before C# 7.0

Before C# 7.0, switch statements were primarily used with simple types like bool, char, string, integral types, enumerations, and their corresponding nullable types. Here's an example of a switch statement:

switch (player.Position)
{
 case "Forward":
    action = "Shoot the ball";
    break;
 case "Midfielder":
    action = "Control the game";
    break;
 case "Defender":
    action = "Defend";
    break;
 default:
    action = "Play in a different position";
    break;
}

C# 7.0: Pattern Matching in Switch Statements

C# 7.0 introduced pattern matching in switch statements, allowing for more expressive and type-safe code. This feature enabled developers to switch on any type and use patterns to match and extract values from the object being switched on. For instance, you could now directly switch on a player and use type patterns to check if they are a forward, midfielder, or defender:

switch (player)
{
 case Forward forward:
    action = $"{forward.Name} shoots the ball";
    break;
 case Midfielder midfielder:
    action = $"{midfielder.Name} controls the game";
    break;
 case Defender defender:
    action = $"{defender.Name} defends";
    break;
 default:
    action = "Play in a different position";
    break;
}

Moreover, C# 7.0 introduced when conditions for cases, allowing for more complex matching logic based on the properties of the object being matched:

case Forward forward when forward.SkillLevel >= 8:
 action = $"{forward.Name} takes a shot";
 break;

C# 8.0: Switch Expressions

C# 8.0 further enhanced switch statements with the introduction of switch expressions, which provide a more concise and readable syntax. Switch expressions eliminate the need for break statements and allow for a more functional programming style. Here's an example of a switch expression:

string action = player.Position switch
{
 "Forward" => "Shoot the ball",
 "Midfielder" => "Control the game",
 "Defender" => "Defend",
 _ => "Play in a different position",
};

This syntax is not only more concise but also safer, as it avoids the risk of forgetting a break statement, which could lead to unintended fall-through behavior.

C# 9.0: Enhanced Pattern Matching

C# 9.0 took pattern matching in switch expressions to the next level with the introduction of relational patterns and pattern combinators. This allowed for even more expressive and powerful matching logic, including matching on ranges, logical combinations, and more. For example, you could now match on a player's skill and power level directly within a switch expression:

string action = player switch
{
 Forward forward when forward.SkillLevel is >= 8 and forward.PowerLevel is > 70 => $"{forward.Name} takes a shot",
 Midfielder midfielder => $"{midfielder.Name} controls the game",
 Defender defender => $"{defender.Name} defends",
 _ => "Play in a different position",
};

This evolution of switch statements in C# has made the language more expressive and powerful, enabling developers to write more concise, readable, and type-safe code.

Conclusion

The evolution of switch statements in C# from basic type matching to the powerful pattern matching and switch expressions of C# 9.0 has significantly improved the language's expressiveness and safety. These enhancements have allowed developers to write more concise, readable, and type-safe code, making C# a more powerful and versatile language for a wide range of applications.