OOP Course
Сьогодні

Підрозділ 9.2

Патерн властивостей

Розглядає property pattern: зіставлення за значеннями властивостей, switch expression, змінні в патернах і вкладені властивості об'єктів.

9.2. Патерн властивостей

Патерн типів (9.1) перевіряє, чим є об'єкт. Але часто нас цікавить не тільки тип, а й конкретні значення його властивостей: «чи є це пацієнт з активним статусом і пріоритетом вище 2?». Для цього існує патерн властивостей (property pattern) — він дозволяє перевіряти відповідність значень полів об'єкта прямо у виразі is або switch.

Синтаксис і анатомія

Патерн властивостей записується у фігурних дужках: { Властивість: значення }. Двокрапка тут не присвоєння, а порівняння: «властивість має це значення». Значенням може бути константа, null, інший патерн (у тому числі реляційний > 2) або var для захоплення.

Патерн властивостей: анатомія та варіанти

Патерн властивостей може стояти окремо або бути частиною складнішого патерну, де зліва вказано тип:

// Тільки властивості (без перевірки типу)
if (patient is { Status: "Active" })

// Тип + властивості разом
if (patient is Patient { Status: "Active", Priority: > 2 })

У другій формі спочатку перевіряється тип (Patient), і якщо він збігається — перевіряються властивості.

Базовий приклад у клінічному контексті

Зверніть увагу: Priority: > 3 — це поєднання патерну властивостей з реляційним патерном. Значення Priority перевіряється не на рівність, а на виконання умови > 3. Патерни в C# вкладаються один в одного.

Захоплення значення через var

Іноді нам потрібно не лише перевірити значення властивості, а й зберегти його у змінну для подальшого використання у виразі результату. Для цього замість конкретного значення пишуть var ім'я:

string GetWelcome(Patient? p) => p switch
{
    { Status: "Active", Department: var dept } => $"Пацієнт активний, відділення: {dept}",
    { Status: var s }                          => $"Статус: {s}",
    null                                       => "Пацієнт не знайдений"
};

Department: var dept означає: «захопити значення властивості Department у змінну dept» — і тоді використати dept у рядку результату. Перевірка типу при цьому не виконується: var завжди успішно збігається з будь-яким значенням (у тому числі null).

Вкладені об'єкти (C# 10+)

Якщо об'єкт містить вкладені об'єкти, патерн властивостей може заглиблюватись у них. До C# 10 для цього потрібен був вкладений патерн:

// До C# 10 — явне вкладення
if (patient is { Department: { Name: "Кардіологія" } })

// C# 10+ — скорочений точковий запис
if (patient is { Department.Name: "Кардіологія" })

Обидва варіанти еквівалентні, але точковий синтаксис C# 10 значно компактніший.

Порожній патерн властивостей {}

Фігурні дужки без вмісту {} — це особливий випадок: він збігається з будь-яким non-null об'єктом:

string Describe(Patient? p) => p switch
{
    { Status: "Active" } => "Активний пацієнт",
    { }                  => "Пацієнт (не активний)", // будь-який не-null
    null                 => "Null"
};

{} часто стоїть передостанньою гілкою в switch як «запасний варіант для не-null» перед явною перевіркою на null.

Поєднання типового та властивісного патернів

Обидва патерни можна поєднувати: спочатку перевірка типу, потім — властивостей. Це особливо зручно в ієрархіях:

string GetInfo(MedicalStaff s) => s switch
{
    Doctor { IsOnLeave: false, Specialty: var spec } => $"Лікар на зміні: {spec}",
    Doctor { IsOnLeave: true }                       => "Лікар у відпустці",
    Nurse  { Ward: var ward }                        => $"Медсестра: палата {ward}",
    _                                                => "Персонал"
};

Тут Doctor { IsOnLeave: false, Specialty: var spec } — патерн типу Doctor (type pattern), що одночасно перевіряє властивість IsOnLeave (property pattern) і захоплює Specialty у змінну spec (var capture).

Такі поєднання роблять switch expression потужним інструментом для опису складної бізнес-логіки у компактній, декларативній формі — без глибоких вкладених if-else.

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