OOP Course
Сьогодні

Підрозділ 9.Q

Питання для самоконтролю

Питання для самоконтролю — Розділ 9. Pattern matching 9.1. Патерн типів 1. Що таке pattern matching у C і яку проблему він вирішує порівняно зі старим підходом через is + явний cast? 2. Що виведе наступний код

Питання для самоконтролю — Розділ 9. Pattern matching

9.1. Патерн типів

  1. Що таке pattern matching у C# і яку проблему він вирішує порівняно зі старим підходом через is + явний cast?

  2. Що виведе наступний код і чому?

    object value = "Гіпертонія";
    if (value is string s)
        Console.WriteLine(s.ToUpper());
    else
        Console.WriteLine("не рядок");
    Console.WriteLine(s); // чи компілюється цей рядок?
  3. Поясніть, у чому різниця між трьома формами:

    // Форма A
    if (staff is Doctor) { Doctor doc = (Doctor)staff; doc.PrescribeMeds(); }
    // Форма B
    Doctor? doc = staff as Doctor;
    if (doc != null) doc.PrescribeMeds();
    // Форма C
    if (staff is Doctor doc) doc.PrescribeMeds();

    Яка форма є найкращою і чому?

  4. Поясніть різницю між switch statement і switch expression. Коли варто обирати кожен варіант? Який з них повертає значення?

  5. Чому в switch конкретніші типи мають іти перед базовими? Що станеться, якщо розмістити MedicalStaff перед Doctor? Чи попередить компілятор про помилку?

  6. Напишіть метод Describe(object obj), який через switch expression повертає рядок опису для: int (значення числа), string (значення рядка), null (рядок "null"), будь-якого іншого типу (назва типу через GetType().Name).

  7. Що таке constant pattern і де він використовується? Поясніть, чим is not null відрізняється від != null з точки зору компілятора.

  8. Порівняйте switch expression з type pattern і класичний ланцюг if-else + cast за такими критеріями: кількість операцій для перевірки типу, ризик InvalidCastException, можливість повертати значення, підтримка нових типів у ієрархії.


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

  1. Що таке патерн властивостей і чим він доповнює патерн типів? Запишіть синтаксис у двох формах: без перевірки типу і з перевіркою типу одночасно.

  2. Що виведе наступний код?

    var p = new Patient("Коваль", "Active", priority: 2);
    string result = p switch
    {
        { Status: "Active", Priority: > 3 } => "Терміново",
        { Status: "Active", Priority: > 1 } => "Плановий",
        { Status: "Active" }                => "Рутинний",
        _                                   => "Інше",
    };
    Console.WriteLine(result);
  3. Навіщо в патерні властивостей використовується var ім'я замість конкретного значення? Наведіть приклад, коли це зручно.

  4. Поясніть різницю між синтаксисом вкладених об'єктів до C# 10 і після C# 10:

    // До C# 10
    if (patient is { Department: { Name: "Кардіологія" } })
    // C# 10+
    if (patient is { Department.Name: "Кардіологія" })

    Чи є між ними функціональна різниця?

  5. Що означає патерн {} (порожні фігурні дужки) у switch expression? Чим він відрізняється від _?

  6. Спроєктуйте switch expression для класу MedicalStaff з підкласами Doctor і Nurse, де для лікаря потрібно перевіряти IsOnLeave і Specialty, а для медсестри — Ward. Поєднайте type pattern та property pattern.

  7. Чому вираз Priority: > 3 у патерні властивостей є поєднанням двох різних видів патернів? Поясніть, як вони вкладаються.

  8. Знайдіть помилку у наступному коді і поясніть, як її виправити:

    string GetStatus(Patient? p) => p switch
    {
        { Status: "Active" } => "Активний",
        {}                   => "Неактивний",
        null                 => "Null"
    };

9.3. Патерни кортежів

  1. Що таке кортежний патерн і коли його слід обирати замість патерну властивостей або патерну типів? Наведіть відмінну рису сценарію застосування.

  2. Що виведе наступний код?

    string result = ("Хірургія", "Ніч") switch
    {
        ("Кардіологія", "День")  => "Плановий",
        ("Хірургія",    "День")  => "Операційний зал",
        ("Хірургія",    _)       => "Ургентна хірургія",
        (_,             "День")  => "Денний прийом",
        _                        => "Позаплановий",
    };
    Console.WriteLine(result);
  3. Поясніть роль discard (_) в кортежному патерні. Чим він відрізняється від var?

  4. Чому порядок arm-ів у кортежному switch має принципове значення? Що станеться, якщо arm з _ розмістити першим?

  5. Напишіть функцію string GetRiskLevel(int systolic, int age), яка за допомогою кортежного патерну визначає рівень ризику: критичний (тиск >= 180), підвищений + похилий вік (>= 140, >= 60), підвищений молодший, норма.

  6. Що означає поява >= 60 and < 120 в позиції кортежного патерну? Які ще патерни можна вставляти в позиції кортежу?

  7. Що відбувається у runtime, якщо жоден arm у switch expression не збігається і відсутній _? Як цього уникнути?

  8. Порівняйте кортежний патерн і вкладені if-else для логіки, яка залежить від двох незалежних вхідних значень. Які переваги і недоліки кожного підходу?


9.4. Позиційний патерн

  1. Що таке позиційний патерн і в чому його відмінність від кортежного патерну? Яка технічна вимога до класу, щоб він підтримував позиційний патерн?

  2. Поясніть три кроки, які виконує компілятор при зіставленні об'єкта з позиційним патерном (pat1, pat2).

  3. Чому позиційний record автоматично підтримує позиційний патерн без додаткового коду? Що генерує компілятор для record VitalSigns(double Temperature, int Pulse)?

  4. Що виведе наступний код?

    public record VitalSigns(double Temperature, int Pulse, int OxygenSat);
    var v = new VitalSigns(38.8, 105, 96);
    string result = v switch
    {
        (>= 39.0, > 90, _)          => "КРИТИЧНО",
        (>= 38.5, _, _)             => "Жар",
        (_, _, < 90)                => "Гіпоксія",
        (var t, var p, var o2)      => $"Стан: {t} {p} {o2}",
    };
    Console.WriteLine(result);
  5. Клас Appointment містить три поля: PatientName, Type, Department. У Deconstruct розкрито лише Type і Department. Чому не PatientName? Як тоді отримати PatientName при зіставленні?

  6. Напишіть клас BloodPressure з полями Systolic і Diastolic, додайте Deconstruct, і реалізуйте метод string Assess(BloodPressure bp) через позиційний патерн.

  7. Порівняйте кортежний та позиційний патерни за такими критеріями: тип вхідних даних, вимоги до класу, типовий сценарій використання.

  8. Чи можна поєднати позиційний патерн з патерном властивостей в одному arm? Якщо так — наведіть приклад; якщо ні — поясніть чому.


9.5. Реляційний та логічний патерни

  1. Що таке реляційний патерн і чим він відрізняється від звичайного оператора порівняння >? У яких місцях коду може стояти реляційний патерн?

  2. Поясніть принципову різницю між && та and у наступних фрагментах:

    if (temp > 37.5 && temp < 39.0) { ... }   // A
    if (temp is > 37.5 and < 39.0) { ... }    // B

    Чи однаковий результат? Чи однакова природа операторів?

  3. Що виведе наступний код?

    double[] temps = { 34.5, 36.6, 37.8, 39.2 };
    foreach (var t in temps)
    {
        string r = t switch
        {
            < 35.0              => "Гіпотермія",
            >= 35.0 and < 36.0  => "Нижче норми",
            >= 36.0 and <= 37.0 => "Норма",
            > 37.0 and < 38.5   => "Субфебрильна",
            _                   => "Жар або вище",
        };
        Console.WriteLine($"{t}: {r}");
    }
  4. Яка різниця між not null як патерном і != null як умовою? Як компілятор трактує is not null?

  5. Поясніть пріоритет операторів and та or у патернах. Що означає вираз temperature is < 35 or > 39? Чи потрібні дужки для явного групування?

  6. Напишіть метод string AssessPulse(int pulse), який через логічний патерн визначає: брадикардія (< 60), тахікардія (> 100), норма (60–100), критична тахікардія (> 150).

  7. Покажіть три місця, де можна використовувати реляційний патерн: після is, в позиції кортежного патерну, в патерні властивостей. Наведіть конкретні приклади коду.

  8. Чому not Doctor у контексті staff is not Doctor є патерним оператором, а не логічним запереченням? Що саме заперечує not у цьому виразі?


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

  1. Що таке патерн списків (list patterns)? В якій версії C# вони з'явились і які типи підтримують цей патерн?

  2. Чому IEnumerable<T> без Count/Length не підтримується патерном списків? Що генерує компілятор для перевірки [a, b, c]?

  3. Що виведе наступний код?

    int[] data = { 130, 120, 95, 72 };
    string result = data switch
    {
        []              => "Порожній",
        [var single]    => $"Одне: {single}",
        [> 100, .., > 100] => "Стійка тахікардія",
        [var f, .., var l] when f > l + 20 => $"Спадання: {f}{l}",
        [var f, .., var l] => $"Стан: {f}..{l}",
    };
    Console.WriteLine(result);
  4. Поясніть синтаксис .. (slice) у патерні списків. Скільки разів він може з'являтися в одному патерні і чому?

  5. Що означає патерн [var first, .., var last]? Що буде, якщо масив містить рівно 2 елементи? Що якщо 1 елемент?

  6. Напишіть метод string ParseCommand(string[] args), який через патерн списків обробляє команди: ["add", var name] → додати, ["remove", var id] → видалити, ["list"] → список, [] → порожня команда, _ → невідома команда.

  7. Як поєднати патерн списків з патерном властивостей в одній умові? Наведіть приклад з and.

  8. Для яких практичних задач патерн списків є особливо виразним інструментом? Назвіть принаймні три сценарії. Чому він непридатний для IEnumerable<T> з великою кількістю елементів?

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