Підрозділ 9.5
Реляційний та логічний патерни
Розглядає relational і logical patterns: порівняння через <, <=, комбінування умов через and/or та заперечення через not.
9.5. Реляційний та логічний патерни
У попередніх секціях патерни порівнювали значення на рівність: "Active", true, null. Але в медицині (та загалом у числовій логіці) рішення ухвалюються на основі діапазонів: температура вище 38.5°C — жар; тиск від 140 — гіпертонія. Для цього у C# 9 введено реляційний та логічний патерни.
Реляційний патерн
Реляційний патерн (relational pattern) перевіряє значення за допомогою операторів <, >, <=, >=:
temperature switch
{
< 36.0 => "Гіпотермія",
>= 38.5 => "Жар",
_ => "Норма"
}Важливо: реляційний патерн не є оператором порівняння. Це патерн — тобто він може стояти не лише у switch, а й після is, у позиції кортежного патерну, всередині патерну властивостей тощо:
if (temperature is > 38.5) { ... } // після is
(temp, pulse) switch { (> 38.5, > 100) => } // в позиції кортежу
{ Priority: >= 3 } // в патерні властивостей
Логічний патерн: and, or, not
Логічний патерн дозволяє комбінувати кілька патернів через and, or, not. Ключова особливість: and, or, not тут — це патернні оператори, а не логічні оператори &&, ||, !.
Різниця принципова:
&&і||— оператори над булевими значеннями:x > 5 && x < 10andіorу патернах — оператори над патернами:> 5 and < 10
// Звичайна умова (bool-вирази):
if (temp > 37.5 && temp < 39.0) { ... }
// Логічний патерн (комбінація патернів):
if (temp is > 37.5 and < 39.0) { ... }Результат той самий, але форма запису в switch є значно виразнішою.
Пріоритет: and вищий за or, як множення вище за додавання. Для явного групування використовуйте дужки:
// (< 35 or > 39) — критичні значення
temperature is < 35 or > 39
// not (>= 36 and <= 37) — не нормальна
temperature is not (>= 36.0 and <= 37.0)Реляційний патерн у клінічному сценарії
Кожен arm покриває рівно один інтервал, і разом вони покривають всю числову вісь. Компілятор аналізує вичерпність: якщо _ відсутній і є непокриті значення — попередження.
Логічний патерн: and, or, not у дії
not з типовим патерном
not може заперечувати не лише реляційні вирази, а й типові патерни:
if (staff is not Doctor)
Console.WriteLine("Не лікар — не може виписувати рецепти");
// В switch:
string role = staff switch
{
not null and not Doctor => "Медперсонал (не лікар)",
Doctor doc => $"Лікар: {doc.Specialty}",
null => "Відсутній"
};not null — це патернний еквівалент перевірки != null. Компілятор трактує його як null-check pattern і може застосовувати null-state analysis.
Де можна використовувати реляційні та логічні патерни
Реляційні та логічні патерни не прив'язані до switch — вони можуть стояти у будь-якому місці, де стоїть патерн:
// Після is:
if (temperature is >= 37.5 and < 39.5) { ... }
// В позиції кортежного патерну:
(temp, pulse) switch { (>= 37.5, > 100) => "..." }
// В патерні властивостей:
patient is { Age: > 60 and < 90, Priority: >= 3 }
// Навіть у декларативному присвоєнні:
bool isFever = temperature is >= 37.5;Саме ця композиційність — можливість вкладати патерни один в одний — є головною силою pattern matching у C#.