Pattern matching
Test the shape of data and pull values out in one step: type, property, relational, logical and list patterns with is and switch.
is with a type pattern
object item = new Beam("B1", 9.5); // old way: test, then castif (item is Beam){ var b1 = (Beam)item; Console.WriteLine(b1.Mark);} // pattern: test and declare a typed variable togetherif (item is Beam b && b.Length > 8) Console.WriteLine($"{b.Mark} is a long beam"); record Beam(string Mark, double Length); Output
B1 B1 is a long beam
switch expressions with patterns
| Pattern | Matches when… | Example |
|---|---|---|
null, 0, "IPE300" | ||
Beam b | ||
> 8, <= 0 | ||
>= 1 and <= 5, not null | ||
{ Length: > 8, Profile: "IPE300" } | ||
_ | ||
when guard | int n when n % 2 == 0 |
Property patterns on real data
static string Classify(Beam b) => b switch{ { Length: <= 0 } => "invalid", { Profile: "HEA200" or "HEA300", Length: > 6 } => "heavy span", { Length: > 8 } => "long", { Length: < 2 } => "stub", _ => "standard"}; Console.WriteLine(Classify(new Beam("B1", "HEA200", 7.5)));Console.WriteLine(Classify(new Beam("B2", "IPE200", 1.2))); record Beam(string Mark, string Profile, double Length); Output
heavy span stub
not null
if (selected is not null) Highlight(selected);if (input is not (null or "")) Process(input);Tuple patterns
static string Rps(string a, string b) => (a, b) switch{ ("rock", "scissors") or ("scissors", "paper") or ("paper", "rock") => "A wins", var (x, y) when x == y => "draw", _ => "B wins"};Console.WriteLine(Rps("paper", "rock")); Output
A wins
List patterns (C# 11)
static string Describe(int[] v) => v switch{ [] => "empty", [var only] => $"one item: {only}", [var first, .., var last] => $"from {first} to {last}",};Console.WriteLine(Describe(new[] { 4, 8, 15, 16 })); Output
from 4 to 16
Practice
static string Shipping(decimal weightKg, bool express) with a switch expression on the tuple (weightKg, express): ≤ 1 kg express → "Rs 150", ≤ 1 kg → "Rs 60", ≤ 10 kg express → "Rs 400", ≤ 10 kg → "Rs 180", anything heavier → "Freight". Negative weight → throw.
Show the solution
static string Shipping(decimal weightKg, bool express) => (weightKg, express) switch{ ( < 0, _) => throw new ArgumentOutOfRangeException(nameof(weightKg)), ( <= 1, true) => "Rs 150", ( <= 1, false) => "Rs 60", ( <= 10, true) => "Rs 400", ( <= 10, false) => "Rs 180", _ => "Freight"}; Console.WriteLine(Shipping(0.5m, true));Console.WriteLine(Shipping(7m, false));Console.WriteLine(Shipping(25m, true)); Output
Rs 150 Rs 180 Freight
Remember
isandswitchcan test type, values and properties in one expression.Patterns: type, constant, relational, and/or/not, property, tuple, list,_.Arms are tested top to bottom; put specific ones first and _last.Patterns declare typed variables, removing manual casts.