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.0
if (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