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

Pattern matching in switch in C Sharp (C#) - Deep Dive

Choose your learning style9 modes available
Overview - Pattern matching in switch
What is it?
Pattern matching in switch is a way to check a value against different shapes or types and run code based on which pattern fits. Instead of just comparing values, it can look inside objects, check types, or test conditions. This makes decisions in code clearer and more powerful. It helps write less code while handling many cases.
Why it matters
Without pattern matching in switch, programmers must write many if-else statements or nested checks, which can be confusing and error-prone. Pattern matching makes code easier to read and maintain, especially when working with complex data. It helps catch mistakes early and makes programs more flexible to change. This improves software quality and developer happiness.
Where it fits
Before learning this, you should know basic C# syntax, how switch statements work, and understand types and variables. After this, you can explore advanced pattern matching features, like recursive patterns and using pattern matching in expressions or LINQ queries.
Mental Model
Core Idea
Pattern matching in switch lets you compare a value to different shapes or types and run code based on which pattern fits best.
Think of it like...
It's like sorting mail: instead of just checking the address, you look inside the envelope to see if it's a letter, a package, or a postcard, and then decide where to send it.
Value to check
   │
   ▼
┌───────────────┐
│   switch      │
│ ┌───────────┐ │
│ │ Pattern 1 │─┬─> Action 1
│ ├───────────┤ │
│ │ Pattern 2 │─┬─> Action 2
│ ├───────────┤ │
│ │ Pattern 3 │─┬─> Action 3
│ └───────────┘ │
└───────────────┘
Build-Up - 7 Steps
1
FoundationBasic switch statement review
🤔
Concept: Understand how a simple switch statement works with constant values.
In C#, a switch statement checks a value against fixed cases. For example: switch (number) { case 1: Console.WriteLine("One"); break; case 2: Console.WriteLine("Two"); break; default: Console.WriteLine("Other"); break; } This runs the code for the matching case.
Result
If number is 1, it prints "One"; if 2, prints "Two"; otherwise "Other".
Knowing how switch works with fixed values sets the stage for understanding how pattern matching extends this idea to more complex checks.
2
FoundationIntroduction to pattern matching basics
🤔
Concept: Learn that pattern matching lets you check types and conditions, not just fixed values.
Instead of only matching exact values, you can check if a variable is a certain type or meets a condition: switch (obj) { case int i: Console.WriteLine($"Integer {i}"); break; case string s: Console.WriteLine($"String '{s}'"); break; default: Console.WriteLine("Unknown type"); break; } This runs code depending on the type of obj.
Result
If obj is 42, prints "Integer 42"; if "hello", prints "String 'hello'".
Understanding that switch can check types opens up more flexible and readable code than many if-else type checks.
3
IntermediateUsing relational and logical patterns
🤔Before reading on: do you think switch can check if a number is greater than 10 directly? Commit to yes or no.
Concept: Learn how to use relational patterns like >, < and combine patterns with logical operators in switch cases.
C# allows patterns like: switch (number) { case > 10: Console.WriteLine("Greater than 10"); break; case <= 10: Console.WriteLine("10 or less"); break; } You can also combine patterns: switch (obj) { case int i when i % 2 == 0: Console.WriteLine("Even number"); break; case int i: Console.WriteLine("Odd number"); break; } This uses conditions to refine matches.
Result
Numbers greater than 10 print "Greater than 10"; even numbers print "Even number".
Knowing that switch can use conditions and relational checks makes it a powerful tool for decision-making beyond simple equality.
4
IntermediateProperty patterns for object matching
🤔Before reading on: do you think switch can check if a person's age property is over 18 directly? Commit to yes or no.
Concept: Learn how to match objects by their properties inside switch cases using property patterns.
You can check properties inside objects: switch (person) { case { Age: >= 18 }: Console.WriteLine("Adult"); break; case { Age: < 18 }: Console.WriteLine("Minor"); break; } This looks inside the person object to decide.
Result
If person.Age is 20, prints "Adult"; if 15, prints "Minor".
Understanding property patterns lets you write clear code that inspects object details without extra if statements.
5
IntermediateCombining patterns with 'and', 'or', 'not'
🤔Before reading on: can you combine multiple conditions in one switch case using keywords like 'and' or 'or'? Commit to yes or no.
Concept: Learn how to combine multiple patterns logically in switch cases for complex matching.
C# supports combining patterns: switch (obj) { case int i and > 0 and < 100: Console.WriteLine("Positive number less than 100"); break; case string s or null: Console.WriteLine("String or null"); break; case not null: Console.WriteLine("Not null"); break; } This lets you express complex rules clearly.
Result
Numbers between 1 and 99 print the first message; strings or null print the second.
Knowing how to combine patterns reduces code duplication and makes complex conditions easy to read.
6
AdvancedRecursive patterns for nested objects
🤔Before reading on: do you think switch can check nested properties inside objects recursively? Commit to yes or no.
Concept: Learn how to match patterns inside nested objects using recursive patterns in switch.
You can check deep inside objects: switch (order) { case { Customer: { Age: >= 18 }, Total: > 100 }: Console.WriteLine("Adult customer with big order"); break; case { Customer: { Age: < 18 } }: Console.WriteLine("Minor customer"); break; } This inspects nested properties in one place.
Result
Orders with adult customers and total over 100 print the first message.
Understanding recursive patterns lets you handle complex data structures elegantly in switch statements.
7
ExpertPerformance and compiler optimizations
🤔Before reading on: do you think pattern matching in switch always compiles to simple jump tables? Commit to yes or no.
Concept: Explore how the compiler translates pattern matching in switch and its impact on performance.
The compiler generates code based on patterns. Simple constant matches become jump tables for speed. Complex patterns become if-else chains or calls to helper methods. Understanding this helps write efficient patterns and avoid slow code. For example, many type checks may slow down compared to simple value matches.
Result
Well-designed patterns run fast; complex ones may add overhead.
Knowing how pattern matching compiles helps write code that balances clarity and performance in real applications.
Under the Hood
Pattern matching in switch works by the compiler generating code that tests the input value against each pattern in order. For simple constant patterns, it uses jump tables or lookup tables for fast dispatch. For type patterns, it inserts type checks and casts. For property and recursive patterns, it generates code that accesses properties and applies nested tests. Logical patterns combine these tests with boolean logic. The runtime evaluates these tests sequentially until one matches, then runs the associated code.
Why designed this way?
Pattern matching was designed to make code more readable and expressive while keeping performance reasonable. Earlier, programmers wrote many nested if-else statements, which were hard to read and maintain. The design balances expressiveness with compiler optimizations, allowing simple cases to be very fast and complex cases to be possible without losing clarity. Alternatives like separate if-else chains were less structured and more error-prone.
Input value
   │
   ▼
┌───────────────┐
│ Compiler      │
│ generates    │
│ code to test │
│ patterns    │
└───────────────┘
   │
   ▼
┌───────────────┐
│ Runtime       │
│ evaluates     │
│ patterns in  │
│ order         │
└───────────────┘
   │
   ▼
┌───────────────┐
│ Executes      │
│ matching case │
└───────────────┘
Myth Busters - 4 Common Misconceptions
Quick: Does a switch pattern matching case always check all patterns before stopping? Commit to yes or no.
Common Belief:Switch pattern matching checks all cases every time before choosing one.
Tap to reveal reality
Reality:Switch stops checking as soon as it finds the first matching pattern and runs that case.
Why it matters:Thinking all cases run wastes time and leads to misunderstanding how to order cases for correct behavior.
Quick: Can pattern matching in switch only check exact values? Commit to yes or no.
Common Belief:Switch pattern matching only works with exact value matches like numbers or strings.
Tap to reveal reality
Reality:It can check types, properties, conditions, and combine patterns, not just exact values.
Why it matters:Underestimating pattern matching limits its use and leads to verbose if-else code instead.
Quick: Does using many complex patterns in switch always improve performance? Commit to yes or no.
Common Belief:More complex pattern matching always makes code faster and better.
Tap to reveal reality
Reality:Complex patterns can slow down code because they generate more checks and casts at runtime.
Why it matters:Ignoring performance tradeoffs can cause slow applications and hard-to-find bugs.
Quick: Can you use pattern matching in switch to mutate the matched object? Commit to yes or no.
Common Belief:Pattern matching in switch can change the matched object's properties directly.
Tap to reveal reality
Reality:Pattern matching only reads and tests values; it does not modify the object.
Why it matters:Trying to mutate inside patterns leads to confusion and misuse of the feature.
Expert Zone
1
Patterns are checked in order, so placing more specific patterns before general ones avoids unreachable code.
2
Using 'when' clauses in switch cases allows adding extra conditions beyond pattern shape, but can affect performance.
3
The compiler sometimes caches type tests or property accesses to optimize repeated pattern checks.
When NOT to use
Avoid pattern matching in switch when performance is critical and patterns are very complex; in such cases, manual if-else with caching or specialized methods may be faster. Also, for very simple equality checks, classic switch or dictionary lookups might be clearer.
Production Patterns
In real-world C# code, pattern matching in switch is used for parsing input data, handling different message types in network code, and simplifying validation logic. It often replaces long if-else chains and improves maintainability in large codebases.
Connections
Functional programming pattern matching
Pattern matching in switch builds on the same idea of matching data shapes and types found in functional languages like F# or Haskell.
Knowing functional pattern matching helps understand C#'s approach and its limitations compared to full functional languages.
Type systems in programming languages
Pattern matching relies on the language's type system to check and cast types safely during matching.
Understanding static and dynamic typing clarifies why some patterns are allowed and how type safety is maintained.
Decision trees in machine learning
Pattern matching in switch is like a decision tree that tests conditions step-by-step to classify input.
Seeing switch as a decision tree helps grasp how ordering and specificity affect matching efficiency and correctness.
Common Pitfalls
#1Writing overlapping patterns in wrong order causing unreachable code.
Wrong approach:switch (obj) { case object o: Console.WriteLine("Any object"); break; case string s: Console.WriteLine("String"); break; }
Correct approach:switch (obj) { case string s: Console.WriteLine("String"); break; case object o: Console.WriteLine("Any object"); break; }
Root cause:More general patterns placed before specific ones prevent the specific cases from ever running.
#2Using 'when' conditions that throw exceptions or have side effects inside switch cases.
Wrong approach:switch (number) { case int i when (10 / i) > 1: Console.WriteLine("Safe"); break; }
Correct approach:switch (number) { case int i when i != 0 && (10 / i) > 1: Console.WriteLine("Safe"); break; }
Root cause:Not guarding against invalid operations in 'when' clauses causes runtime errors.
#3Trying to assign to variables inside pattern matching cases incorrectly.
Wrong approach:switch (obj) { case int i = 5: Console.WriteLine(i); break; }
Correct approach:switch (obj) { case int i when i == 5: Console.WriteLine(i); break; }
Root cause:Pattern matching tests values; it does not assign new values in the pattern syntax.
Key Takeaways
Pattern matching in switch lets you write clearer, more expressive code by checking types, properties, and conditions, not just fixed values.
It improves code readability and maintainability by replacing complex if-else chains with structured patterns.
Patterns are checked in order, so the sequence of cases affects which code runs and must be carefully planned.
Understanding compiler behavior helps balance pattern complexity with performance in real applications.
Knowing when and how to use pattern matching effectively is key to writing modern, robust C# code.