C sharp - Pattern Matching Enhancements in C# (C# 8–12)
Pattern matching in C# has evolved significantly in recent versions, becoming a powerful feature for writing cleaner, safer, and more expressive code. It allows developers to test data against patterns and extract values in a concise way. While early versions of C# only supported basic type checks, modern versions (C# 8 through C# 12) introduce advanced forms such as relational, logical, property, positional, and list patterns.
1. Basic Concept of Pattern Matching
Pattern matching enables checking a value against a specific shape or condition and optionally extracting data from it. It is commonly used with constructs like is, switch, and switch expressions.
Example:
if (obj is string s)
{
Console.WriteLine(s.Length);
}
Here, the variable is both checked and assigned in a single step.
2. Relational Patterns
Relational patterns allow comparison using operators like <, >, <=, and >= directly within pattern matching.
Example:
int number = 25;
string result = number switch
{
< 18 => "Minor",
>= 18 and < 60 => "Adult",
>= 60 => "Senior"
};
This improves readability compared to traditional if-else chains and keeps conditions compact.
3. Logical Patterns
Logical patterns combine multiple conditions using:
-
and -
or -
not
Example:
int temp = 30;
if (temp is > 20 and < 35)
{
Console.WriteLine("Comfortable temperature");
}
Example with or:
if (temp is < 0 or > 40)
{
Console.WriteLine("Extreme temperature");
}
Example with not:
if (temp is not 25)
{
Console.WriteLine("Temperature is not ideal");
}
These operators allow expressing complex logic more declaratively.
4. Property Patterns
Property patterns are used to match values based on the properties of an object. This is particularly useful when working with classes or structured data.
Example:
class Person
{
public string Name { get; set; }
public int Age { get; set; }
}
Person p = new Person { Name = "John", Age = 30 };
if (p is { Age: > 18 })
{
Console.WriteLine("Adult");
}
Nested property patterns:
if (p is { Name: "John", Age: > 25 })
{
Console.WriteLine("Specific match");
}
This eliminates the need for multiple property checks.
5. Positional Patterns
Positional patterns work with objects that support deconstruction. They allow matching values based on position rather than property names.
Example:
record Point(int X, int Y);
Point pt = new Point(10, 20);
if (pt is (10, 20))
{
Console.WriteLine("Exact match");
}
With conditions:
if (pt is (> 0, > 0))
{
Console.WriteLine("Point in positive quadrant");
}
6. Switch Expressions
Switch expressions are a more concise version of the traditional switch statement and are heavily used with pattern matching.
Example:
int score = 85;
string grade = score switch
{
>= 90 => "A",
>= 75 => "B",
>= 50 => "C",
_ => "Fail"
};
They return values directly and reduce boilerplate code.
7. List Patterns (C# 11+)
List patterns allow matching arrays or collections based on their structure.
Example:
int[] numbers = { 1, 2, 3 };
if (numbers is [1, 2, 3])
{
Console.WriteLine("Exact sequence");
}
With conditions:
if (numbers is [> 0, > 0, > 0])
{
Console.WriteLine("All positive numbers");
}
You can also use discards:
if (numbers is [1, _, 3])
{
Console.WriteLine("Matches pattern");
}
8. Combined Patterns
Different pattern types can be combined to create complex matching logic.
Example:
object input = new Person { Name = "Alice", Age = 28 };
if (input is Person { Age: > 25 } and not null)
{
Console.WriteLine("Valid adult person");
}
This shows how type, property, and logical patterns work together.
9. Advantages of Modern Pattern Matching
-
Improves readability by reducing nested conditions
-
Reduces boilerplate code
-
Makes code more declarative
-
Minimizes runtime errors with safer checks
-
Supports complex data structures effectively
10. Practical Use Cases
Pattern matching is widely used in:
-
Data validation
-
API request handling
-
Parsing structured data
-
Game development logic
-
State-based workflows
For example, in API development, pattern matching can validate incoming request objects and route logic accordingly.
Conclusion
Pattern matching enhancements in modern C# versions significantly improve how developers write conditional logic. By introducing relational, logical, property, positional, and list patterns, C# allows concise and expressive handling of complex data structures. This leads to cleaner, more maintainable code and aligns C# with modern programming paradigms.