C# 7.0 introduced pattern matching with type tests, but it was limited to checking the type and extracting the value. Accessing properties required additional code after the pattern match.
C# 8.0 extends pattern matching to support property patterns and positional patterns, allowing you to match against object properties and nested structures directly within the pattern itself. This enables deeply nested pattern matching in a single expression.
Code
C#
public decimal CalculateDiscount(Order order) => order switch
{
{ Items.Count: > 10, Customer.IsVip: true } => 0.20m,
{ Items.Count: > 10 } => 0.10m,
{ Customer.IsVip: true } => 0.05m,
_ => 0m
};
public string Describe(object obj) => obj switch
{
Person { Address: { City: "London" } } => "Londoner",
Person { Age: >= 18, Name: var name } => $"Adult named {name}",
Car { Make: "Nissan", Model: "Leaf" } => "Nissan Leaf",
_ => "Unknown"
};
C#
public decimal CalculateDiscount(Order order)
{
if (order.Items.Count > 10 && order.Customer.IsVip)
return 0.20m;
if (order.Items.Count > 10)
return 0.10m;
if (order.Customer.IsVip)
return 0.05m;
return 0m;
}
public string Describe(object obj)
{
if (obj is Person person)
{
if (person.Address?.City == "London")
return "Londoner";
if (person.Age >= 18)
return $"Adult named {person.Name}";
}
if (obj is Car car && car.Make == "Nissan" && car.Model == "Leaf")
return "Nissan Leaf";
return "Unknown";
}
Notes
- Property patterns use the syntax
{ PropertyName: pattern }
to match against object properties - You can nest patterns arbitrarily deep to match complex object structures
- Positional patterns work with types that have a
Deconstruct
method - Combine with switch expressions for concise, readable code
- Use
var
patterns to capture values:{ Name: var n }
captures the Name property into variablen
- Supports relational patterns like
>
,<
,>=
,<=
for numeric comparisons