Підрозділ 5.Q
Питання для самоконтролю
Питання для самоконтролю — Розділ 5. Обробка винятків 5.1. Конструкція try..catch..finally 1. Що таке виняток exception у C ? Від якого базового класу успадковуються всі класи винятків? Хто і коли створює об'єк
Питання для самоконтролю — Розділ 5. Обробка винятків
5.1. Конструкція try..catch..finally
Що таке виняток (exception) у C#? Від якого базового класу успадковуються всі класи винятків? Хто і коли створює об'єкт винятку?
Опишіть порядок виконання блоків
try,catch,finallyу двох сценаріях: коли виняток виникає і коли не виникає.Що виведе наступний код?
try { Console.WriteLine("try"); int x = int.Parse("abc"); Console.WriteLine("після Parse"); } catch { Console.WriteLine("catch"); } finally { Console.WriteLine("finally"); } Console.WriteLine("після блоку");Чи виконається
finally, якщо уcatchтеж виник виняток? Чи виконаєтьсяfinally, якщо уtryвжитоreturn?Поясніть механізм поширення винятку по стеку викликів. Якщо метод
AвикликаєB, який викликаєC, а виняток виникає вC— де він може бути перехоплений?Порівняйте два підходи:
try { int age = int.Parse(s); }іif (int.TryParse(s, out int age)). Коли перший підхід кращий, коли другий? Чому не варто використовуватиtry...catchдля передбачуваних сценаріїв?Для чого може використовуватись
try...finallyбез блокуcatch? Наведіть приклад, де це потрібно, і поясніть: чи перехоплює така конструкція виняток?Спроєктуйте метод
ParseAndRegister(string name, string ageStr), який парсить вік, реєструє пацієнта і гарантує виведення рядка"Операцію завершено"у будь-якому разі — навіть при помилці. Використайтеtry...catch...finally.
5.2. Блок catch та фільтри винятків
Чим відрізняються три форми блоку
catch? Запишіть синтаксис кожної і поясніть, що перехоплює кожна.Що виведе наступний код?
try { string s = null; Console.WriteLine(s.Length); } catch (FormatException) { Console.WriteLine("FormatException"); } catch (NullReferenceException ex) { Console.WriteLine($"NullRef: {ex.Message}"); } catch (Exception ex) { Console.WriteLine($"Exception: {ex.Message}"); }Якщо поставити
catch (Exception ex)першим серед кількох блоківcatch, що станеться? Чи виникне помилка компіляції?Поясніть оператор
whenу блоціcatch. Що відбувається, якщо тип винятку збігається, але умоваwhenповертаєfalse?Напишіть метод
ProcessInput(string input), що обробляєFormatExceptionпо-різному: окремо якщо рядок порожній (черезwhen) і окремо для всіх інших некоректних значень.Поясніть антипатерн «ковтання винятку» — порожній або беззмістовний блок
catch. Чому він небезпечний у медичній або фінансовій системі?Розробник написав
catch (ArgumentException)передcatch (ArgumentOutOfRangeException). Яка проблема? Як виправити?Є три блоки
catch:FormatException,OverflowException,Exception. Для яких вхідних значеньint.Parse(s)спрацює кожен з них? Наведіть конкретні приклади рядків-вхідних даних.
5.3. Типи винятків. Клас Exception
Перелічіть і коротко опишіть п'ять властивостей класу
Exception. Яка з них найчастіше використовується у повідомленнях користувачу?Що виведе
ex.GetType().Name, якщоexперехоплено черезcatch (Exception ex), а реальний виняток єFormatException?Що таке
InnerException? Наведіть сценарій, де воно корисне для діагностики помилки.Що виведе цей код і в якому порядку?
string input = "999999999999999"; try { int val = int.Parse(input); } catch (OverflowException ex) { Console.WriteLine($"Overflow: {ex.Message}"); } catch (FormatException ex) { Console.WriteLine($"Format: {ex.Message}"); } catch (Exception ex) { Console.WriteLine($"Other: {ex.Message}"); }Поясніть правило: «конкретніший тип — раніше». Чому
ArgumentOutOfRangeExceptionмає стояти передArgumentExceptionу ланцюжкуcatch?Що означає «виняток зупиняє виконання
try»? Напишіть приклад, де уtryє три рядки коду, і виняток виникає на другому. Що відбувається з третім рядком?Як
catch (Exception ex)виступає «страхувальним мережем»? Чи слід його завжди додавати? В яких ситуаціях він обов'язковий, а в яких зайвий?Для яких ситуацій призначені такі типи винятків:
NullReferenceException,IndexOutOfRangeException,InvalidCastException,ArgumentNullException? Наведіть по одному рядку коду, що спровокує кожен.
5.4. Генерація винятку та оператор throw
Навіщо генерувати виняток вручну через
throw? Наведіть приклад бізнес-правила, порушення якого технічно не є помилкою, але потребуєthrow.Чим відрізняються
throw;(без аргументу) іthrow ex;(з аргументом) у блоціcatch? Яку помилку допускають при використанніthrow ex;?Що виведе цей код?
void Process(string name) { try { Validate(name); Console.WriteLine("OK"); } catch (ArgumentException ex) { Console.WriteLine($"Caught: {ex.Message}"); } } void Validate(string name) { if (string.IsNullOrEmpty(name)) throw new ArgumentException("Ім'я порожнє"); } Process(""); Process("Іван");Що таке ланцюжок винятків (
InnerException)? Напишіть метод, що перехоплюєFormatExceptionі загортає його уInvalidOperationExceptionзі збереженням оригіналу.Яке призначення оператора
nameofуthrow new ArgumentOutOfRangeException(nameof(age), ...)? Що повертаєnameof(age)і чому це краще, ніж рядок"age"?Напишіть метод
SetAge(int age), що кидаєArgumentOutOfRangeExceptionякщо вік менший за 0 або більший за 150. Загорніть виклик у блокtry...catchі виведіть повідомлення про помилку разом з некоректним значенням.Розробник написав такий код:
catch (Exception ex) { Log(ex); throw ex; }Знайдіть помилку і поясніть наслідки. Як виправити?
Де правильніше розміщувати
throwдля валідації аргументів: на початку методу чи в середині? Чому так зручніше для читача коду і для відлагодження?
5.5. Створення класів винятків
Чому варто створювати власні класи винятків для доменних помилок, якщо у .NET вже є понад 200 вбудованих типів?
Яка мінімальна реалізація необхідна для власного класу винятку? Що обов'язково вказати і навіщо?
Від якого класу краще успадковувати власний виняток, якщо він описує некоректний аргумент методу? А якщо стан об'єкта не дозволяє виконати операцію?
Що виведе цей код?
class AppException : Exception { public string Code { get; } public AppException(string message, string code) : base(message) { Code = code; } } try { throw new AppException("Недостатньо прав", "AUTH_ERR"); } catch (Exception ex) { Console.WriteLine(ex.Message); if (ex is AppException app) Console.WriteLine($"Код: {app.Code}"); }Поясніть перевагу зберігання доменних даних у власному виняткові (наприклад, поле
InvalidAge) порівняно з формуванням рядкуMessage.Спроєктуйте ієрархію винятків для інтернет-магазину: базовий
ShopException(з полемOrderId) та два конкретних —OutOfStockException(зProductName) іPaymentException(зAmount). Напишіть метод обробки замовлення, що кидає обидва типи і ловить їх окремо.Яка конвенція щодо іменування власних класів винятків? Наведіть три правильні і три неправильні назви.
Розробник вирішив не створювати власний клас, а покласти всі деталі у рядок
Message. Порівняйте цей підхід із власним класом з властивостями. Де кожен з них кращий?
5.6. Пошук блоку catch при обробці винятків
Опишіть дві фази роботи CLR при виникненні винятку: фазу пошуку і фазу розкрутки стека. Що відбувається у кожній фазі і в якому порядку виконуються
finally-блоки?Дано ланцюжок викликів
Main→A→B→C. Виняток виникає уC. У якому порядку CLR перевіряє рівні стека у фазі пошуку?Що виведе цей код?
void A() { try { B(); } catch (FormatException ex) { Console.WriteLine($"A catch: {ex.Message}"); } finally { Console.WriteLine("A finally"); } } void B() { try { C(); } catch (NullReferenceException) { Console.WriteLine("B catch NullRef"); } finally { Console.WriteLine("B finally"); } } void C() { try { int.Parse("abc"); } finally { Console.WriteLine("C finally"); } } A();Виняток виник у методі на 3-му рівні стека.
catchзнайдено на 1-му рівні. Якіfinally-блоки виконаються і в якому порядку?Якщо CLR не знаходить відповідного
catchна жодному рівні стека, що відбувається? Чи гарантовано при цьому виконанняfinally-блоків?Поясніть патерн «логування + перекидання»:
catch (Exception ex) { Log(ex); throw; }. Чому це краще, ніж повністю ковтати виняток або перехоплювати лише для логування і не перекидати?Зверніть увагу: у прикладі нижче рядок після
try...catchуSaveRecordне виконується, хоча у методі єfinally. Поясніть чому.void SaveRecord(string id, string input) { try { int age = int.Parse(input); Console.WriteLine("Збережено"); } catch (NullReferenceException) { Console.WriteLine("NullRef"); } finally { Console.WriteLine("SaveRecord finally"); } Console.WriteLine("Після try у SaveRecord"); // коли виконується? } SaveRecord("P1", "abc");Спроєктуйте трирівневий ланцюжок:
UI()→Service()→Repository().RepositoryкидаєInvalidOperationException.Serviceлогує помилку черезfinallyі перекидає.UIперехоплює і відображає повідомлення користувачу. Напишіть повний код і поясніть порядок виконання кожного блоку.