Let's assume the following records (class).
record class Person(string Name, int Age, Address Address);record class Address(string Country);
Before property pattern matching we did something like this.
if (person?.Name != null && (person?.Age == 18 || (person?.Age >= 21 && person.Age <= 25))&& person.Name.StartsWith("A")&& person.Address.Country.Contains("land")){Console.WriteLine($"{person.Name} authorized.");}
With property pattern matching we can do this in a more declarative way.
Combined with the var pattern we can write more readable and less code by using the newly created variables.
if (person is { Name: not null, Name: var name, Age: 18 or >= 21 and <= 25, Address.Country: var country }&& name.StartsWith("A")&& country.Contains("land")){Console.WriteLine($"{name} authorized.");}
We do NOT have to check for null with property pattern matching, because the C# compiler will "lowering" your high level C# code (syntax sugar) into lower level C# code (desugar).
See how C# lowering is done with sharplab
Null checks with pattern matching
if (person is { }){Console.WriteLine("Person is not null");}// New since C# 9.0if (person is not null){Console.WriteLine("Person is not null");}
This gets lowered to:
if ((object)person != null){Console.WriteLine("Person is not null");}
Because of the cast to System.Object, overloaded != operator will not be called!
Nice to know: declarative vs imperative programming
- With declarative programming you write code that describes what you want done.
- With imperative programming, it is about the implementation details.
C# documentation:
https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/operators/patterns#property-pattern
https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/operators/patterns#var-pattern