List patterns

C# 11.0 .NET 7.0

Published Updated Author Jeffrey T. Fritz Reading time

Match specific positions and elements in arrays or lists using patterns, reducing complex index-based conditionals to readable, declarative expressions.

List patterns, introduced in C# 11.0 (.NET 7.0), extend pattern matching to arrays and lists. You can match elements at specific positions, use slice patterns (..) to match variable-length sequences, and combine patterns to express complex list structure checks. This feature transforms verbose index-based logic into clear, declarative patterns.

Why it matters

  • Replaces verbose index-based conditionals with readable pattern expressions.
  • Enables matching on list structure (first, last, or middle elements) without explicit indexing.
  • Integrates seamlessly with switch expressions and pattern matching.
  • Makes code intent clearer and less error-prone than manual index arithmetic.

Cautions

  • List patterns work with collections implementing IEnumerable; performance depends on the collection type (arrays are efficient; linked lists require enumeration).
  • Slice patterns consume remaining elements; ensure your intent matches (do you want to ignore them or process them?).
  • A non-matching list pattern does not throw; it simply evaluates as no match. Still include a fallback arm in switch expressions for clarity and safety.
  • Debugging list patterns can be harder than explicit index checks; test thoroughly.

Match array elements by position and value

List patterns allow you to match specific positions and values in an array or list, enabling powerful pattern-based control flow.

Valid since C# 11.0

Without var

int[] numbers = [1, 2, 3];
if (numbers.Length >= 2 && numbers[0] == 1 && numbers[1] == 2)
{
    Console.WriteLine("Starts with 1, 2");
}
else if (numbers.Length == 3 && numbers[0] == 1 && numbers[2] == 3)
{
    Console.WriteLine("Pattern: 1, any, 3");
}

With var

int[] numbers = [1, 2, 3];
string result = numbers switch
{
    [1, 2, ..] => "Starts with 1, 2",
    [1, _, 3] => "Pattern: 1, any, 3",
    _ => "No match"
};
Console.WriteLine(result);

Slice patterns for variable-length lists

List patterns with slice patterns (`..`) allow matching the first, last, or middle elements while ignoring or capturing the rest.

Valid since C# 11.0

string Summarize(int[] numbers) => numbers switch
{
    [var first, .. var rest] => $"First: {first}, Rest count: {rest.Length}",
    [var only] => $"Single element: {only}",
    [] => "Empty list"
};

Learn more

List patterns (Microsoft Learn)