Loading...

Pattern Matching

Pattern Matching in C# is a powerful feature that allows developers to test an object against a pattern and, if the pattern matches, extract information from it. Introduced in C# 7.0 and enhanced in later versions, Pattern Matching enables more expressive, readable, and maintainable code when handling complex data types or conditional logic. It is particularly important in scenarios involving polymorphism, object hierarchies, and structured data, where traditional conditional statements may become verbose and error-prone.
Developers use Pattern Matching in C# for type checks, value comparisons, and deconstructing objects, enabling concise and declarative programming. Core C# concepts involved include object-oriented principles, type hierarchies, control flow, and structured data handling. Understanding syntax variations—such as is, switch, property patterns, tuple patterns, and positional patterns—is crucial to leveraging Pattern Matching effectively in C# applications.
This tutorial focuses on practical problem-solving using Pattern Matching in real-world C# projects. Readers will learn how to implement advanced matching scenarios, optimize decision-making logic, and write safer, more maintainable code. By mastering Pattern Matching, developers can improve algorithm efficiency, reduce error-prone code paths, and implement robust solutions in backend systems, API development, and software architecture.

Basic Example

text
TEXT Code
using System;

namespace PatternMatchingExample
{
public class Shape {}
public class Circle : Shape
{
public double Radius { get; }
public Circle(double radius) => Radius = radius;
}
public class Rectangle : Shape
{
public double Width { get; }
public double Height { get; }
public Rectangle(double width, double height) => (Width, Height) = (width, height);
}

class Program
{
static void Main(string[] args)
{
Shape shape = new Circle(5.0);

string result = shape switch
{
Circle c => $"Circle with radius {c.Radius}",
Rectangle r => $"Rectangle with width {r.Width} and height {r.Height}",
_ => "Unknown shape"
};

Console.WriteLine(result);
}
}

}

In the code above, we define a simple class hierarchy with Shape as the base class and Circle and Rectangle as derived types. This setup demonstrates polymorphism and object-oriented principles, essential for real-world C# applications. The switch expression uses Pattern Matching to check the runtime type of the shape object.
The Circle c and Rectangle r patterns not only test the type but also create local variables (c and r) to access properties directly. This eliminates the need for explicit casting and reduces the risk of runtime exceptions. The default _ pattern handles cases where the object does not match any known type, ensuring robust error handling and preventing unexpected crashes.
This example highlights several advanced C# concepts: type safety, object deconstruction, and concise conditional logic. By using Pattern Matching, developers can write cleaner and more maintainable code when processing heterogeneous data structures, such as collections of shapes or polymorphic entities in software systems. Understanding these patterns allows for optimized algorithms in decision-making logic, avoiding nested if-else statements, which can be error-prone and harder to maintain.

Practical Example

text
TEXT Code
using System;
using System.Collections.Generic;

namespace PatternMatchingAdvanced
{
public abstract class Employee
{
public string Name { get; set; }
protected Employee(string name) => Name = name;
}

public class Manager : Employee
{
public int TeamSize { get; set; }
public Manager(string name, int teamSize) : base(name) => TeamSize = teamSize;
}

public class Developer : Employee
{
public string PrimaryLanguage { get; set; }
public Developer(string name, string language) : base(name) => PrimaryLanguage = language;
}

class Program
{
static void ProcessEmployee(Employee employee)
{
switch (employee)
{
case Manager m when m.TeamSize > 10:
Console.WriteLine($"Senior Manager: {m.Name}, Team Size: {m.TeamSize}");
break;
case Manager m:
Console.WriteLine($"Manager: {m.Name}, Team Size: {m.TeamSize}");
break;
case Developer d:
Console.WriteLine($"Developer: {d.Name}, Language: {d.PrimaryLanguage}");
break;
default:
Console.WriteLine($"Unknown employee type: {employee.Name}");
break;
}
}

static void Main(string[] args)
{
var employees = new List<Employee>
{
new Manager("Alice", 12),
new Developer("Bob", "C#"),
new Manager("Charlie", 5)
};

foreach (var emp in employees)
{
ProcessEmployee(emp);
}
}
}

}

This practical example extends Pattern Matching to real-world employee management. Here, we demonstrate the use of switch with type patterns and when guards. when conditions allow additional logic checks, such as identifying a senior manager with a team size greater than 10. This shows how Pattern Matching integrates algorithms, conditional logic, and OOP principles in C# projects.
The ProcessEmployee method illustrates handling heterogeneous collections safely and efficiently. Developers can access properties directly after matching, avoiding explicit casting, which enhances code safety and readability. Using Pattern Matching with collections allows for optimized data processing and decision-making workflows, critical in enterprise applications.
This example also emphasizes best practices: handling unknown types with a default case, following C# naming conventions, and structuring code for maintainability. It highlights how advanced Pattern Matching can improve software quality, reduce bugs, and facilitate future system scalability. Performance is also considered, as Pattern Matching avoids redundant type checks or casting, which can degrade application efficiency.

C# best practices and common pitfalls

text
TEXT Code
* Always include a default case in `switch` expressions to handle unexpected types.
* Use `when` guards for additional conditional logic to prevent complex nested `if` statements.
* Avoid unnecessary casting; Pattern Matching provides type safety and reduces runtime errors.
* Prefer `switch` expressions over `if-else` chains for clarity and maintainability.
* Beware of matching null values; always check for null when appropriate.
* Optimize Pattern Matching in performance-critical sections by minimizing complex object creation.
* Avoid memory leaks by not retaining unnecessary references in matched patterns.
* Use descriptive variable names in patterns to improve code readability.
* Test Pattern Matching logic thoroughly to catch unexpected cases.
* Apply consistent C# naming conventions and follow SOLID principles in class hierarchies.

📊 Reference Table

C# Element/Concept Description Usage Example
Type Pattern Matches object type and casts it to local variable case Circle c: Console.WriteLine(c.Radius);
Property Pattern Matches object properties case Rectangle r when r.Width > 10: …
Tuple Pattern Matches tuple elements case (int x, int y) when x > y: …
Switch Expression Concise conditional logic with patterns var result = shape switch { Circle c => c.Radius, _ => 0 };
when Guard Adds additional conditional logic to patterns case Manager m when m.TeamSize > 10: …

Mastering Pattern Matching in C# empowers developers to write safer, cleaner, and more efficient code. Key takeaways include understanding type, property, and tuple patterns, using when guards effectively, and implementing switch expressions for concise conditional logic. Pattern Matching connects deeply with C#’s OOP features, algorithms, and data structures, enabling robust solutions in real-world projects.
Next steps for learners include exploring recursive patterns, record deconstruction, and pattern matching in LINQ queries. Applying these techniques in backend systems, APIs, and enterprise applications will strengthen algorithmic thinking and software architecture skills. Recommended resources include Microsoft’s official C# documentation, advanced C# books, and hands-on projects that challenge developers to implement Pattern Matching in varied scenarios. Continuous practice and real-world experimentation will solidify mastery of this advanced C# feature.

🧠 Test Your Knowledge

Ready to Start

Test Your Knowledge

Test your understanding of this topic with practical questions.

3
Questions
🎯
70%
To Pass
♾️
Time
🔄
Attempts

📝 Instructions

  • Read each question carefully
  • Select the best answer for each question
  • You can retake the quiz as many times as you want
  • Your progress will be shown at the top