OOP Course
Сьогодні

Підрозділ 9.6

Патерни списків

Пояснює list patterns: повний збіг зі списками й масивами, підстановку _, slice-патерн .., отримання елементів у змінні та поєднання з властивостями колекцій.

9.6. Патерни списків

Патерни списків (list patterns) — найновіший різновид патернів у C#, доданий у версії C# 11 (.NET 7, 2022). Вони дозволяють зіставляти масиви та колекції зі структурними зразками: перевіряти кількість елементів, значення на конкретних позиціях, першого і останнього елементів, а також довільний «зріз» посередині.

Які типи підтримуються

Патерн списків працює з будь-яким типом, що є лічильним (має властивість Length або Count) і індексованим (має індексатор з int або Index). Інтерфейс тут не потрібен — компілятор шукає члени за іменами:

  • T[] — масиви будь-якого типу;
  • List<T>, IList<T> — списки;
  • Span<T>, ReadOnlySpan<T> — span-и.

Для slice з захопленням (.. var x) потрібно більше: індексатор з Range або метод Slice(int, int). Він є в масивів, string, Span<T> і List<T> (метод Slice додано в .NET 8), але немає в IList<T>: il is [var a, .. var rest] дає помилку CS1503, хоча il is [1, ..] (slice без захоплення) компілюється. Захоплений slice масиву — це новий масив-копія.

IEnumerable<T> без Count/Length не підтримується — компілятор не може ефективно перевіряти довжину ліниво-обчислюваних послідовностей.

Як компілятор перевіряє патерн

Для патерну [a, b, c] компілятор генерує приблизно:

collection.Length == 3 &&
collection[0] matches a &&
collection[1] matches b &&
collection[2] matches c

Тобто спочатку перевіряється довжина, потім — кожна позиція через відповідний патерн. Це важливо для продуктивності: якщо довжина не збігається — позиції не перевіряються.

Синтаксис: елементи та slice

Патерн списків: синтаксис елементів та sliceПатерн списків: синтаксис елементів та slice

Елементи у дужках перевіряють позиції. В кожній позиції може стояти будь-який патерн — константа, _, реляційний, var:

readings is [72, 88, 95, 101, 88]  // точний збіг усіх 5 елементів
readings is [> 70, _, _, > 90, _]  // реляційні в позиціях
readings is [var first, .., var last] // захопити крайні

Slice .. — це «довільна кількість елементів» (включно з нулем). Він може стояти лише один раз у патерні:

[72, ..]       // починається з 72
[.., 88]       // закінчується на 88
[72, .., 88]   // починається 72, закінчується 88, між ними будь-що
[_, .., _]     // ≥2 елементи
[..]           // будь-яка довжина ≥0

Сам slice теж можна захопити у змінну: .. var назва (див. приклад нижче).

Клінічний приклад: аналіз серії вимірювань

Захоплення slice у змінну

Частину між крайніми елементами можна захопити у змінну через .. var назва. Це дозволяє далі обробляти «середину» масиву:

Поєднання патерну списків з патерном властивостей

Якщо потрібно перевірити і структуру списку, і властивості колекції, обидва патерни можна поєднати через and:

if (readings is { Length: >= 3 } and [var first, _, _, .. var rest])
{
    Console.WriteLine($"Перший: {first}, решта: {string.Join(",", rest)}");
}

Тут { Length: >= 3 } — патерн властивостей (перевіряє довжину), and [...] — патерн списків (зіставляє структуру). Разом — єдина умова. Щоправда, в цьому конкретному прикладі перевірка довжини надлишкова: [var first, _, _, .. var rest] сам по собі вимагає щонайменше трьох елементів. Комбінація має сенс, коли властивість обмежує те, чого патерн списку не виражає, — наприклад, верхню межу: { Length: <= 10 } and [> 100, ..] («коротка серія, що почалась із тахікардії»).

Де патерни списків практично корисні

Патерни списків особливо виразні в задачах, де структура масиву сама по собі несе інформацію:

  • Парсинг рядків команд: ["add", var name, var value], ["remove", var id], []
  • Валідація форматів: масив токенів повинен починатись і закінчуватись певними маркерами
  • Обробка кадрів протоколу: перший байт — тип, останній — контрольна сума
  • Аналіз трендів: [> threshold, .., < threshold] — значення перетнуло поріг

Для великих або нескінченних послідовностей (IEnumerable<T>) патерни списків не підходять — там слід використовувати LINQ або явні цикли.

Розроблено Tomka Yurii · © 2026 ·