loading experience

C#

Pattern matching in modern C#: records, switch and list patterns

From switch expressions to list patterns: how to express business rules readably, checked by the compiler.

Pattern matching in modern C#: records, switch and list patterns

Pattern matching has transformed the way conditional logic is written in C#. Combined with record types, it lets you express complex rules in a few readable lines.

Cases are evaluated top-down: the most specific go first.
Cases are evaluated top-down: the most specific go first.

Switch expressions with properties

public record Order(decimal Total, string Country, bool PremiumCustomer);

decimal Shipping(Order o) => o switch
{
    { PremiumCustomer: true }           => 0m,
    { Country: "IT", Total: >= 50m }    => 0m,
    { Country: "IT" }                   => 5.90m,
    { Total: >= 150m }                  => 9.90m,
    _                                   => 19.90m
};

Rules read from top to bottom and the compiler warns you if a case can never be reached.

Relational and logical patterns

string Band(int age) => age switch
{
    < 0              => throw new ArgumentOutOfRangeException(nameof(age)),
    < 18             => "minor",
    >= 18 and < 65   => "adult",
    _                => "senior"
};

List patterns

List patterns match the shape of an array or list: first element, last, length, slices.

string Describe(string[] args) => args switch
{
    []                       => "no command",
    ["help"]                 => "show help",
    ["copy", var from, var to] => $"copy {from} to {to}",
    ["log", .. var rest]     => $"log with {rest.Length} options",
    _                        => "unknown command"
};

Tips

  • Put the most specific cases before the generic ones.
  • Avoid overly long switch expressions: beyond a dozen cases consider a rules table.
  • With closed hierarchies of records, the compiler helps you not forget cases.
Comments (0)

No comments yet.

Leave a comment