Pattern Matching in C#: cleaner, more elegant code
If you've ever written nested conditions or complex checks in C#, pattern matching might be your best ally for making your code more readable and elegant.
No more checking each property one by one, no more juggling complex null conditions. The code is easier to read, less error-prone and, above all, it expresses intent clearly.
Before / after: the property pattern
Before
if (movie != null
&& movie.Genre == "Drama"
&& movie.Rating >= 8.0
&& movie.ReleaseYear >= 2015)
{
Console.WriteLine("Top drama since 2015.");
}
With pattern matching
if (movie is { Genre: "Drama", Rating: >= 8.0, ReleaseYear: >= 2015 })
{
Console.WriteLine("Top drama since 2015.");
}
One single expression: the null check is implicit (is fails if movie is null), the properties are checked together, and the condition reads like a sentence.
Switch expressions
Combined with switch expressions, pattern matching replaces entire if/else trees:
var discount = customer switch
{
{ Type: CustomerType.Premium, YearsActive: > 5 } => 0.20m,
{ Type: CustomerType.Premium } => 0.10m,
{ Orders.Count: 0 } => 0m,
null => throw new ArgumentNullException(nameof(customer)),
_ => 0.05m
};
Each case fits on one line, order acts as priority, and the compiler warns you when a case isn't covered.
Patterns worth knowing
Relational and logical patterns: if (age is >= 18 and < 65) replaces two comparisons and reads naturally.
The modern null check: if (order is not null) is safer than != because it ignores operator overloads.
List patterns (C# 11): if (codes is [var first, .., var last]) destructures a collection in a single expression.
Takeaway: pattern matching doesn't change what your code does, it changes what it says. A condition that reads like a sentence means faster code reviews and one less bug slipping through.
This article comes from one of my LinkedIn posts (in French): join the discussion ↗