Підрозділ 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.