Pattern Matching In C#

Introduction

 
In today’s article we will look at pattern matching in C#. This is a way to match certain members in our objects or the objects themselves to certain conditions and values. This is an especially useful technique to make our code more concise and readable. We will look at several different patterns for matching.

What is Pattern Matching?

 
In simple terms we can define Pattern Matching as the code we write to test for certain values and conditions. In the past we normally used If and Switch statements for this purpose. Although, these worked perfectly and will also work now, we now also have the choice of more robust code writing options while using these pattern matching techniques. We will look at five patterns in the code below. Different patterns have been introduced with different release versions of C#. However, for this article I will be using C# 9.0, which will have all the patterns discussed in this article.
 

Creating a solution and looking into Pattern Matching

 
First let us create a new console application using Visual Studio 2019 Community Edition.
 
Pattern Matching in C#
 
Pattern Matching in C#
 
Pattern Matching in C#
 
After the project has been created, remember to set the target framework to .NET 5 to use all features up to C# 9.0.
 
Pattern Matching in C#
 
Next, create an Employee class as below,
  1. namespace ConsoleAppPatternMatchingTests  
  2. {  
  3.     class Employee  
  4.     {  
  5.         public int Id { getset; }  
  6.         public string Name { getset; }  
  7.         public int Age { getset; }  
  8.     }  
  9. }  
And add the below code in the Program.cs file,
  1. using System;  
  2. using ConsoleAppPatternMatchingTests;  
  3. // Constant Patterns  
  4. var employee = new Employee() { Id = 1, Name = "John Doe", Age = 0 };  
  5. if (employee.Age is 0)  
  6.     Console.WriteLine($"{employee.Name} has an age of zero");  
  7. // Null Patterns  
  8. var employeeWithNull = new Employee() { Id = 1, Age = 30 };  
  9. if (employeeWithNull.Name is null)  
  10.     Console.WriteLine($"The employee with Id: {employeeWithNull.Id} has a name that is null");  
  11. //Negated Patterns  
  12. var employeeWithoutNull = new Employee() { Id = 1, Name = "John Doe", Age = 30 };  
  13. if (employeeWithoutNull.Name is not null)  
  14.     Console.WriteLine($"{employeeWithoutNull.Name} name is not null");  
  15. //Type Patterns  
  16. var employeeType = new Employee() { Id = 1, Name = "John Doe", Age = 30 };  
  17. if (employeeType is Employee emp)  
  18.     Console.WriteLine($" Employee name is {emp.Name}");  
  19. //Property Patterns  
  20. var employeeProp = new Employee() { Id = 1, Name = "John Doe", Age = 30 };  
  21. if (employeeProp is { Age: 30 })  
  22.     Console.WriteLine($" Employe age is {employeeProp.Age}");  
  23. if (employeeProp is { Age: >25 })  
  24.     Console.WriteLine($" Employee age: {employeeProp.Age} is greater than 25");  
  25. Console.ReadKey();  
Now when we run the application, we see the below output,
 
Pattern Matching in C#
 
Let us examine each one,
  1. // Constant Patterns  
  2. var employee = new Employee() { Id = 1, Name = "John Doe", Age = 0 };  
  3. if (employee.Age is 0)  
  4.     Console.WriteLine($"{employee.Name} has an age of zero");  
In the constant pattern, we are simply comparing a field to a constant value. In the above case we are checking if the age of the employee is zero.
  1. // Null Patterns  
  2. var employeeWithNull = new Employee() { Id = 1, Age = 30 };  
  3. if (employeeWithNull.Name is null)  
  4.     Console.WriteLine($"The employee with Id: {employeeWithNull.Id} has a name that is null");  
In the null pattern, we are checking a value to see if it is null. In the above case we are checking if the name of the employee is null.
  1. //Negated Patterns  
  2. var employeeWithoutNull = new Employee() { Id = 1, Name = "John Doe", Age = 30 };  
  3. if (employeeWithoutNull.Name is not null)  
  4.     Console.WriteLine($"{employeeWithoutNull.Name} name is not null");   
In the negated pattern, we are checking a value to see if it is not null. In the above case we are checking if the name of the employee is not null.
  1. //Type Patterns  
  2. var employeeType = new Employee() { Id = 1, Name = "John Doe", Age = 30 };  
  3. if (employeeType is Employee emp)  
  4.     Console.WriteLine($" Employee name is {emp.Name}");  
In the type pattern we are checking to see the type of an object and at the same time creating an instance of it as well.
  1. //Property Patterns  
  2. var employeeProp = new Employee() { Id = 1, Name = "John Doe", Age = 30 };  
  3. if (employeeProp is { Age: 30 })  
  4.     Console.WriteLine($" Employe age is {employeeProp.Age}");  
  5. if (employeeProp is { Age: >25 })  
  6.     Console.WriteLine($" Employee age: {employeeProp.Age} is greater than 25");  
In the property pattern, we are comparing properties for certain values which could be fixed or also using comparisons like the greater than operator used with the age field in the second example.
 

Summary

 
In this article, we looked at different pattern matching techniques that are available in C# 9.0. Some of these might also be available in earlier versions of C# as well. As you might have noticed all these tasks could have been accomplished using If and switch statements. However, using these techniques makes our code more robust and easier to understand. It adds the Wow factor to our code. Happy coding!