DEV Community

Cover image for C# 6 and Beyond: Revolutionizing Case Analysis with Pattern Matching
waelhabbal
waelhabbal

Posted on

C# 6 and Beyond: Revolutionizing Case Analysis with Pattern Matching

Introduction

C# has evolved significantly over the years, and one of the most impactful changes came with the introduction of pattern matching in C# 6. This feature, coupled with the enhanced switch expression in later versions, has dramatically improved the syntax, readability, and expressiveness of case analysis in C# code.

In this post, we'll delve deep into the world of pattern matching, exploring how it works, its various forms, and how it can be effectively used to write cleaner, more maintainable code.

The is Operator: A First Step

Before we dive into switch statements, let's understand the is operator, which laid the groundwork for pattern matching.

The is operator checks if an expression is compatible with a given type. If it is, it can optionally declare a variable of that type.

object shape = new Circle();
if (shape is Circle circle)
{
    // We can use 'circle' here, which is of type Circle
    Console.WriteLine($"Circle radius: {circle.Radius}");
}
Enter fullscreen mode Exit fullscreen mode

This code checks if shape is a Circle. If so, it declares a new variable circle of type Circle and assigns the converted value to it.

The switch Statement: A New Era

C# 7 introduced significant improvements to the switch statement, allowing it to work with any type, not just integral types and strings. This, combined with pattern matching, opened up new possibilities.

object shape = new Rectangle();
switch (shape)
{
    case Circle c:
        Console.WriteLine($"Circle radius: {c.Radius}");
        break;
    case Rectangle r:
        Console.WriteLine($"Rectangle width: {r.Width}, height: {r.Height}");
        break;
    default:
        Console.WriteLine("Unknown shape");
        break;
}
Enter fullscreen mode Exit fullscreen mode

In this example, the switch statement efficiently determines the type of the shape object and executes the appropriate code block.

Pattern Matching with the switch Expression

C# 8 introduced the switch expression, providing a more concise and functional-style syntax for pattern matching.

object shape = new Circle();
string result = shape switch
{
    Circle c => $"Circle with radius {c.Radius}",
    Rectangle r => $"Rectangle with width {r.Width} and height {r.Height}",
    _ => "Unknown shape"
};
Enter fullscreen mode Exit fullscreen mode

The switch expression evaluates to a value based on the matched pattern.

Types of Patterns

C# supports various patterns, including:

  • Constant patterns: Match literal values.
  • Type patterns: Match types.
  • Var patterns: Match any type.
  • Discard patterns: Match any value and discard it.
  • Property patterns: Match property values.
  • Tuple patterns: Match tuple elements.
  • Positional patterns: Match elements by position.
  • Logical patterns: Combine patterns using and, or, and not.

Example: Using Different Patterns

int age = 25;
string message = age switch
{
    < 18 => "Minor",
    >= 18 and < 65 => "Adult",
    _ => "Senior"
};
Enter fullscreen mode Exit fullscreen mode

This example demonstrates the use of constant, relational, and logical patterns.

Deconstruction and Pattern Matching

C# supports deconstruction, which can be combined with pattern matching to extract values from objects.

(int x, int y) point = (3, 4);
int result = point switch
{
    (0, 0) => 0,
    (var x, var y) when x == y => x * 2,
    (var x, var y) => x + y
};
Enter fullscreen mode Exit fullscreen mode

Additional Features

  • Guard clauses: Use when to add conditions to patterns.
  • Multiple case labels: Combine multiple patterns with the same result.
  • Default case: Handle unmatched cases with the _ pattern.

Conclusion

Pattern matching is a powerful feature that significantly enhances C# code readability and maintainability. By understanding the different types of patterns and how to use them effectively, you can write cleaner, more expressive, and less error-prone code.

Remember: The key to mastering pattern matching is practice. Experiment with different patterns and scenarios to fully grasp its potential.

Would you like to explore specific use cases or dive deeper into any particular aspect of pattern matching?

Top comments (0)