OOP Course
Сьогодні

Підрозділ 5.2

Блок catch та фільтри винятків

Розглядає форми блоку catch, отримання інформації про виняток через змінну та фільтри винятків із when.

5.2. Блок catch та фільтри винятків

Блок catch є серцем механізму обробки винятків. Він визначає, які саме винятки перехоплюються і яку інформацію про помилку надає розробнику. У C# є три форми блоку catch, а також можливість задати додатковий фільтр через when.

Форми блоку catch та фільтр when

Форма 1: catch без параметрів

Найпростіший варіант — catch без вказання типу. Такий блок перехоплює будь-який виняток, незалежно від його типу:

catch
{
    // виконується при будь-якому винятку
}

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

Форма 2: catch з типом винятку

Якщо вказати тип у дужках, блок catch перехопить лише цей тип (або його похідні). Винятки інших типів через цей блок не пройдуть:

catch (FormatException)
{
    // обробляє лише FormatException
}

Тут два блоки catch — кожен обробляє свій тип. Якщо рядок некоректний — спрацьовує FormatException. Якщо число занадто велике — OverflowException. Якщо виникне інший тип помилки — жоден блок не перехопить його.

Важливо: блоки catch перевіряються зверху вниз у порядку оголошення. Спрацьовує перший відповідний.

Форма 3: catch з типом і змінною

Найінформативніша форма: дає доступ до об'єкта винятку через іменовану змінну. Змінна містить усю доступну інформацію про помилку — передусім властивість Message:

catch (FormatException ex)
{
    Console.WriteLine(ex.Message); // деталі помилки
}

Властивість ex.Message містить зрозумілий опис помилки від CLR. Це особливо корисно для логування: у виробничих системах повідомлення про помилку зазвичай записується у журнал, а не виводиться користувачу напряму.

Фільтри винятків: when

Оператор when дозволяє додати умову до блоку catch. Блок спрацює лише якщо умова повертає true:

catch (ExceptionType ex) when (умова)
{
    // виконується лише якщо умова == true
}

Якщо умова false — CLR продовжує шукати наступний відповідний catch, навіть якщо тип збігається.

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

Обидва catch обробляють FormatException, але:

  • перший — лише якщо input порожній (when (string.IsNullOrEmpty(input)))
  • другий — у всіх інших випадках FormatException

Це дозволяє розрізнити різні смислові сценарії для одного типу винятку — без вкладених if у тілі catch.

Антипатерн: «ковтання» винятків

Один із найпоширеніших і найнебезпечніших патернів — блок catch, що не робить нічого або просто виводить повідомлення, але не сигналізує про помилку далі:

// ПОГАНО — помилка «ковтається», програма продовжує роботу з пошкодженим станом:
try
{
    int age = int.Parse(input);
    SaveToDatabase(age);
}
catch (Exception)
{
    // нічого не робимо
}

У медичній системі це особливо небезпечно: якщо SaveToDatabase кинула виняток (зв'язок з БД обірвався), а помилка «ковтнута» — дані пацієнта мовчки не зберігаються. Система вважає, що все добре, але картка так і не записана.

Правила:

  • Ніколи не залишайте catch порожнім у виробничому коді — принаймні логуйте виняток
  • catch (Exception) — тільки на верхньому рівні (main loop, middleware), і лише якщо ви справді знаєте, що з ним робити
  • Якщо не знаєте, як обробити виняток — використовуйте throw;, щоб він «спливав» вище

Порядок блоків catch

Кілька блоків catch перевіряються у порядку оголошення. Є одне важливе правило: загальніший тип має йти після конкретнішого. Наприклад, Exception (базовий тип для всіх) повинен бути останнім, інакше він перехопить усе раніше:

Якщо поставити catch (Exception ex) першим — він перехопить усе, і специфічні блоки ніколи не виконаються. Компілятор попередить про недосяжний код.

Підсумок

Форма Синтаксис Що перехоплює
Без параметрів catch { } Будь-який виняток
З типом catch (FormatException) { } Лише вказаний тип
З типом і змінною catch (FormatException ex) { } Лише вказаний тип + доступ до ex.Message
З фільтром catch (FormatException ex) when (умова) { } Тип збігається і умова true

Блоки перевіряються зверху вниз. Загальніший тип (Exception) завжди ставте останнім.

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