0
0
C Sharp (C#)programming~15 mins

Switch expressions with patterns in C Sharp (C#) - Deep Dive

Choose your learning style9 modes available
Overview - Switch expressions with patterns
What is it?
Switch expressions with patterns in C# let you choose a value based on matching conditions in a clear and concise way. Instead of writing long if-else chains or traditional switch statements, you write expressions that check the shape or value of data. These patterns can match types, values, or even properties inside objects, making your code easier to read and maintain.
Why it matters
Without switch expressions with patterns, code that needs to handle many different cases can become long, repetitive, and hard to follow. This feature helps programmers write cleaner, more expressive code that clearly shows the decision logic. It reduces bugs and makes future changes easier, which is important in real-world software where clarity saves time and effort.
Where it fits
Before learning switch expressions with patterns, you should understand basic C# syntax, variables, and traditional switch statements. After mastering this, you can explore advanced pattern matching, records, and functional programming styles in C#.
Mental Model
Core Idea
Switch expressions with patterns let you pick a result by matching data shapes or values in a simple, readable expression.
Think of it like...
It's like sorting mail by looking at the address: you check if it matches a city, street, or house number pattern, then decide where to send it.
Input Value
   │
   ▼
┌─────────────────────────────┐
│  Match pattern 1 → Result 1 │
│  Match pattern 2 → Result 2 │
│  Match pattern 3 → Result 3 │
│  ...                       │
│  Default pattern → Default  │
└─────────────────────────────┘
   │
   ▼
Output Value
Build-Up - 6 Steps
1
FoundationBasic switch expression syntax
🤔
Concept: Introduces the simple form of switch expressions to select values based on exact matches.
In C#, a switch expression looks like this: var result = value switch { 1 => "One", 2 => "Two", _ => "Other" }; Here, value is checked against 1 and 2. If it matches, the corresponding string is returned. The underscore (_) means 'anything else'.
Result
If value is 1, result is "One"; if 2, "Two"; otherwise "Other".
Understanding the basic syntax shows how switch expressions replace long if-else chains with a clear, concise way to pick results.
2
FoundationUsing patterns in switch expressions
🤔
Concept: Shows how to match more than exact values by using patterns like types or conditions.
Patterns let you check more than just exact values. For example: object obj = 42; var result = obj switch { int i => $"Integer {i}", string s => $"String '{s}'", _ => "Unknown" }; This matches obj's type: if it's an int, it captures it as i; if string, as s.
Result
For obj = 42, result is "Integer 42"; for obj = "hi", result is "String 'hi'".
Patterns let you write flexible matching logic that adapts to the shape or type of data, not just fixed values.
3
IntermediateProperty patterns for nested matching
🤔Before reading on: do you think you can match inside an object's properties directly in a switch expression? Commit to yes or no.
Concept: Introduces property patterns to match objects based on their internal property values.
You can match objects by checking their properties: record Person(string Name, int Age); Person p = new("Alice", 30); var category = p switch { { Age: < 18 } => "Child", { Age: >= 18 and < 65 } => "Adult", { Age: >= 65 } => "Senior", _ => "Unknown" }; This checks the Age property inside Person directly.
Result
For Alice aged 30, category is "Adult".
Property patterns let you write clear, direct conditions on object data without extra code, improving readability and reducing errors.
4
IntermediateCombining patterns with logical operators
🤔Before reading on: can you combine multiple conditions in one pattern using 'and' or 'or'? Commit to yes or no.
Concept: Shows how to use logical operators to combine multiple pattern conditions in switch expressions.
You can combine patterns with 'and', 'or', and 'not': int number = 15; var description = number switch { > 0 and < 10 => "Small positive", >= 10 and <= 20 => "Medium positive", < 0 => "Negative", _ => "Other" }; This matches number ranges using combined conditions.
Result
For number = 15, description is "Medium positive".
Logical operators in patterns let you express complex conditions clearly and compactly, avoiding nested ifs.
5
AdvancedUsing switch expressions with tuples
🤔Before reading on: do you think you can switch on multiple values at once using tuples? Commit to yes or no.
Concept: Demonstrates switching on tuples to match multiple values simultaneously in one expression.
You can create a tuple and switch on it: (int x, int y) point = (3, 4); var quadrant = point switch { ( > 0, > 0) => "Quadrant 1", ( < 0, > 0) => "Quadrant 2", ( < 0, < 0) => "Quadrant 3", ( > 0, < 0) => "Quadrant 4", _ => "On axis" }; This matches the signs of x and y together.
Result
For point (3,4), quadrant is "Quadrant 1".
Tuple patterns let you handle multiple related values at once, making multi-dimensional decisions simple and elegant.
6
ExpertPerformance and evaluation order in switch expressions
🤔Before reading on: do you think all patterns in a switch expression are evaluated every time, or only until one matches? Commit to your answer.
Concept: Explains how switch expressions evaluate patterns in order and stop at the first match, affecting performance and side effects.
Switch expressions check patterns from top to bottom. Once a pattern matches, evaluation stops. For example: var result = value switch { Pattern1 => Result1, Pattern2 => Result2, _ => DefaultResult }; If Pattern1 matches, Pattern2 is never checked. This means expensive checks should go later, and side effects in patterns can be tricky.
Result
Only the first matching pattern's result is used; later patterns are skipped.
Knowing evaluation order helps write efficient and predictable switch expressions, avoiding unnecessary work or unexpected side effects.
Under the Hood
At runtime, the C# compiler translates switch expressions with patterns into efficient code that tests each pattern in order. It uses type checks, comparisons, and property accessors as needed. When a pattern matches, it immediately returns the associated result, skipping the rest. This short-circuiting behavior ensures performance and predictable flow. The compiler also optimizes some patterns into jump tables or decision trees for speed.
Why designed this way?
Switch expressions with patterns were designed to combine clarity and power. Traditional switch statements only matched exact values, which was limiting. Patterns let developers express complex conditions naturally. The ordered evaluation and short-circuiting keep performance predictable. Alternatives like if-else chains were verbose and error-prone, so this design balances expressiveness with efficiency.
Input Value
   │
   ▼
┌─────────────────────────────┐
│ Check Pattern 1? ── Yes ──▶│
│                     │       │
│                     No      │
│                     ▼       │
│ Check Pattern 2? ── Yes ──▶│
│                     │       │
│                     No      │
│                     ▼       │
│       ...                 │
│                     │       │
│ Default Pattern ────▶ Result│
└─────────────────────────────┘
Myth Busters - 4 Common Misconceptions
Quick: Does a switch expression evaluate all patterns even after one matches? Commit to yes or no.
Common Belief:Switch expressions check every pattern every time, so all conditions run regardless of matches.
Tap to reveal reality
Reality:Switch expressions stop checking patterns as soon as one matches, skipping the rest.
Why it matters:Believing all patterns run can lead to inefficient code or unexpected side effects if patterns have code that runs during matching.
Quick: Can switch expressions only match exact values? Commit to yes or no.
Common Belief:Switch expressions only work with exact value matches like traditional switch statements.
Tap to reveal reality
Reality:Switch expressions support complex patterns including type checks, property patterns, relational patterns, and logical combinations.
Why it matters:Thinking they only match exact values limits how you write expressive and concise code, missing out on powerful pattern matching.
Quick: Can you use variables inside patterns to capture matched data? Commit to yes or no.
Common Belief:Patterns cannot capture parts of the matched data for use in the result expression.
Tap to reveal reality
Reality:Patterns can capture variables (like 'int i' or '{ Age: var a }') that you can use in the result expression.
Why it matters:Not knowing this prevents writing concise code that uses matched data directly, leading to more verbose and error-prone code.
Quick: Are switch expressions always more efficient than if-else chains? Commit to yes or no.
Common Belief:Switch expressions are always faster than if-else statements.
Tap to reveal reality
Reality:Performance depends on the patterns and compiler optimizations; sometimes if-else can be faster, especially for simple conditions.
Why it matters:Assuming switch expressions are always better can lead to premature optimization or ignoring simpler solutions.
Expert Zone
1
Patterns can be nested deeply, allowing matching complex data structures in one expression, but this can hurt readability if overused.
2
The compiler generates different IL code depending on pattern complexity, sometimes using jump tables, sometimes cascading ifs, affecting performance subtly.
3
Using discard (_) patterns strategically can simplify code but may hide important cases if not carefully designed.
When NOT to use
Avoid switch expressions with patterns when matching logic requires side effects, complex loops, or asynchronous operations. In such cases, traditional if-else or method calls with clear control flow are better. Also, for very simple conditions, a plain if-else may be clearer.
Production Patterns
In real-world C# code, switch expressions with patterns are used for parsing input, handling different message types, routing commands, and simplifying validation logic. They often appear in combination with records and immutable data to write clean, functional-style code.
Connections
Functional programming pattern matching
Switch expressions with patterns build on the same idea of matching data shapes found in functional languages like F# or Haskell.
Understanding this connection helps appreciate how C# brings powerful functional concepts into an object-oriented language.
Decision trees in machine learning
Switch expressions evaluate patterns in order, similar to how decision trees split data based on conditions.
Seeing switch expressions as a simple decision tree clarifies their evaluation order and efficiency considerations.
Human pattern recognition
Just as humans recognize patterns in faces or speech to make decisions quickly, switch expressions match data patterns to decide program flow.
This cross-domain link shows how programming mimics natural cognitive processes to handle complexity efficiently.
Common Pitfalls
#1Forgetting the default case leads to runtime exceptions.
Wrong approach:var result = value switch { 1 => "One", 2 => "Two" };
Correct approach:var result = value switch { 1 => "One", 2 => "Two", _ => "Other" };
Root cause:Not including a catch-all (_) pattern means the switch expression is not exhaustive, causing errors if no pattern matches.
#2Using complex logic inside patterns causing side effects.
Wrong approach:var result = value switch { _ when ExpensiveCheck() => "Yes", _ => "No" };
Correct approach:bool check = ExpensiveCheck(); var result = check switch { true => "Yes", false => "No" };
Root cause:Putting side-effecting or expensive calls inside patterns can cause unexpected behavior or performance issues.
#3Misusing variable capture leading to scope errors.
Wrong approach:var result = obj switch { int i => i + 1, string s => i.Length // error: i not defined here };
Correct approach:var result = obj switch { int i => i + 1, string s => s.Length };
Root cause:Variables captured in one pattern are not visible in others; misunderstanding scope causes errors.
Key Takeaways
Switch expressions with patterns let you write clear, concise code by matching data shapes and values in one expression.
Patterns go beyond exact matches to include types, properties, and combined conditions, making code more expressive.
Evaluation stops at the first matching pattern, so order matters for correctness and performance.
Including a default (_) pattern ensures your switch expression handles all cases safely.
Understanding this feature unlocks powerful, readable decision logic in modern C# programming.