C# Academy · Lesson

List and Tuple Patterns

Destructure collections.

Lesson 4 of 413 steps

List and Tuple Patterns is a free C# Academy lesson on CoddyKit. This is lesson 4 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the C# Academy learning path, and your progress syncs across the web and the CoddyKit app. The C# Academy course includes 4 lessons in total.

Tuple Patterns

A tuple pattern matches several values at once by wrapping them in parentheses. Each position is matched by its own sub-pattern.

This is ideal for decisions that depend on multiple inputs, like a small state machine or a rock-paper-scissors judge, all in one switch.

int x = 0, y = 5;
string quadrant = (x, y) switch
{
    (0, 0) => "origin",
    (0, _) => "y-axis",
    (_, 0) => "x-axis",
    _ => "plane"
};
System.Console.WriteLine(quadrant);

A Runnable Tuple Switch

Tuple patterns make decision tables readable. Here two booleans pick an action.

Each arm lists a tuple pattern, and the discard _ in a position means that slot can be anything. The final _ arm covers the rest.

using System;

class Program {
    static string Move(bool fwd, bool turn) => (fwd, turn) switch {
        (true, false) => "straight",
        (true, true) => "curve",
        (false, true) => "spin",
        _ => "stop"
    };
    static void Main() => Console.WriteLine(Move(true, true));
}

Binding Inside Tuples

Positions in a tuple pattern can capture values. (0, var y) matches when the first item is 0 and binds the second to y.

You can then use the bound variable in the arm result or in a when guard, mixing matching and extraction in one step.

var point = (0, 7);
string r = point switch
{
    (0, var y) => $"on y-axis at {y}",
    (var x, 0) => $"on x-axis at {x}",
    _ => "elsewhere"
};
System.Console.WriteLine(r);

List Patterns

A list pattern matches arrays and lists by their elements, written with square brackets: [1, 2, 3]. It matches when the length and each element pattern agree.

Introduced in C# 11, list patterns let you branch on sequence shape directly without manual length and index checks.

int[] data = { 1, 2, 3 };
string shape = data switch
{
    [] => "empty",
    [_] => "one",
    [_, _] => "two",
    _ => "many"
};
System.Console.WriteLine(shape);

Matching Exact Elements

List patterns can match specific values per position. [1, 2, 3] matches only that exact three-element sequence.

Mix constants and discards freely: [1, _, 3] matches a length-three list that starts with 1 and ends with 3, ignoring the middle.

using System;

class Program {
    static void Main() {
        int[] a = { 1, 9, 3 };
        bool ok = a is [1, _, 3];
        Console.WriteLine(ok);
    }
}

The Slice Pattern

The slice pattern .. matches any number of elements (including zero) in one position. A list pattern may contain at most one slice.

[1, .., 9] matches any list that starts with 1 and ends with 9, whatever lies between. This is great for head and tail checks.

int[] nums = { 1, 4, 5, 9 };
string r = nums switch
{
    [1, .., 9] => "1..9 bookends",
    _ => "other"
};
System.Console.WriteLine(r);

Capturing a Slice

The slice can capture the skipped elements into a variable using var: [first, .. var rest].

The captured portion is itself an array or list of the matched type, letting you destructure a head element and keep the tail for further processing.

using System;

class Program {
    static void Main() {
        int[] xs = { 10, 20, 30, 40 };
        if (xs is [var head, .. var tail])
            Console.WriteLine($"{head} then {tail.Length} more");
    }
}

Binding Edge Elements

You can bind both ends around a slice: [var first, .., var last] captures the first and last items while ignoring the middle.

This is concise for sequences where only the boundaries matter, such as validating that a route starts and ends at known points.

using System;

class Program {
    static void Main() {
        string[] route = { "A", "B", "C", "D" };
        if (route is [var start, .., var end])
            Console.WriteLine($"{start} -> {end}");
    }
}

List Patterns with Sub-Patterns

Each list position can use any pattern, including relational and logical ones. [> 0, > 0] matches a two-element list of positives.

This composes the full pattern toolbox into sequence matching, so you can validate both shape and content in a single expression.

int[] pair = { 3, 8 };
string r = pair switch
{
    [> 0, > 0] => "both positive",
    [_, _] => "mixed",
    _ => "wrong size"
};
System.Console.WriteLine(r);

Nesting Tuples and Lists

Tuple and list patterns nest inside each other and inside property patterns. A tuple position can hold a list pattern and vice versa.

This lets you match complex structured data, like a labeled sequence, in one expression rather than several nested checks.

using System;

class Program {
    static void Main() {
        (string, int[]) record = ("primes", new[]{ 2, 3 });
        string r = record switch {
            ("primes", [2, ..]) => "starts with 2",
            _ => "other"
        };
        Console.WriteLine(r);
    }
}

Requirements for List Patterns

List patterns work on any type that is countable and indexable: it needs a Length or Count property and an indexer. Arrays, List<T>, and strings qualify.

Slice capture additionally needs a slice method or range indexer. Most built-in collections support both out of the box.

string s = "cat";
bool isCat = s is ['c', 'a', 't'];
System.Console.WriteLine(isCat);

Quick Check

Test your understanding of list and tuple patterns.

Recap

Tuple patterns match multiple values in parentheses; list patterns match sequence shape in brackets, with .. as a slice that can capture the middle via var.

Positions accept any sub-pattern and nest freely. List patterns need a countable, indexable type. You now command the full C# pattern toolbox.

Free to start

Learn C# with an AI tutor — free

Write and run real code in your browser, get instant help from a 24/7 AI tutor, and pick up where you left off on the web or in the app.

Courses
93
Lessons
346

Frequently Asked Questions

Is the “List and Tuple Patterns” lesson free?

Yes — the full text of “List and Tuple Patterns” is free to read here on the web. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the C# Academy course, upgrade to CoddyKit PRO. The C# Academy course includes 4 lessons in total.

What will I learn in “List and Tuple Patterns”?

Destructure collections. You practise C# Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.

Do I need any experience to start C# Academy?

No prior experience is required. C# Academy on CoddyKit is structured for beginners through advanced learners, so you can start here or from the beginning and move at your own pace. This is lesson 4 of 4.

How long does the “List and Tuple Patterns” lesson take?

Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.

Can I write and run code in this C# Academy lesson?

Yes. Every C# Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.

All lessons in this course

  1. switch Expressions
  2. Type and Property Patterns
  3. Relational and Logical Patterns
  4. List and Tuple Patterns
← Back to C# Academy