Підрозділ 5.6
Пошук блоку catch при обробці винятків
Розбирає пошук відповідного catch у стеку викликів і порядок виконання finally при передачі винятку між методами.
5.6. Пошук блоку catch при обробці винятків
Виняток, що виник у методі, не зобов'язаний оброблятися там само. Якщо у поточному методі немає відповідного catch, CLR піднімається вгору по стеку викликів — до того методу, який викликав поточний, і так далі. Це дозволяє централізувати обробку помилок на потрібному рівні, не захаращуючи кожен метод блоками try...catch.
Як CLR шукає обробник: дві фази
Коли виникає виняток, CLR виконує дві окремі фази:
Фаза 1 — пошук: CLR рухається вгору по стеку від місця винятку, перевіряючи кожен рівень на наявність відповідного catch. Поки обробник не знайдено — жодний catch і жодний finally не виконується.
Фаза 2 — розкрутка стека: Щойно відповідний catch знайдено, CLR повертається від місця помилки назад донизу, виконуючи по дорозі всі блоки finally. Потім виконується знайдений catch.

Покроковий приклад
Розглянемо ланцюжок методів клінічної системи: ProcessAdmission → SaveRecord → ParseAge. Виняток виникає у найглибшому методі:
Порядок виведення показує обидві фази чітко:
finally у ParseAge— перший на шляху розкруткиfinally у SaveRecord— другийcatchуProcessAdmission— виконується після всіх finallyfinally у ProcessAdmission— останній"Після try у ProcessAdmission."— виконується, бо виняток перехоплено
Що не виконується
Коли виняток не перехоплено на певному рівні, увесь код після блоку try...catch на цьому рівні пропускається. У прикладі вище:
"Після try у SaveRecord."— не виводиться, хочаSaveRecordмаєfinally- Код у
ParseAgeпісляint.Parse(raw)— не досягається взагалі
Це принципово важливо: виняток негайно перериває нормальне виконання і передає керування механізму пошуку обробника.
Якщо catch не знайдено ніде
Якщо CLR пройде весь стек і не знайде жодного відповідного catch — програма аварійно завершується. При цьому блоки finally можуть не виконатися (залежить від середовища та типу завершення). Саме тому завжди варто мати «страхувальний» catch (Exception ex) на верхньому рівні програми:
Практичний патерн: логування + перекидання
Поширений підхід — логувати помилку на проміжному рівні через finally або catch + throw, а фактично обробляти її вище:
throw; (без аргументу) зберігає оригінальний об'єкт і стек — верхній рівень отримає точне місце першопричини. Якщо написати throw ex; — стек скинеться до місця перекидання, що ускладнює діагностику.
Підсумок: алгоритм CLR при винятку
- Виняток виникає у методі N
- Фаза пошуку: CLR перевіряє рівні стека знизу вгору: N → N-1 → ... → точка входу
- На кожному рівні перевіряє: чи є
catch, чий тип відповідає винятку і чийwhen-фільтр (якщо є) даєtrue - Якщо знайдено → фаза розкрутки: виконує
finallyвід рівня N до рівня знахідки, потім самcatch - Якщо не знайдено ніде → аварійне завершення програми
- Код після
try...catchна рівнях без обробника не виконується; код післяtry...catchна рівні з обробником — виконується нормально