обробка винятків у .net

Я поставив кілька запитань тут і прочитав кілька статей щодо обробки виключень, але не думаю, що я дійсно захоплююся, коли треба, і коли ви не повинні обробляти виняток. З прочитаних статей я стверджую, що "обробляються виключення, які ви можете відновити". Що означає це. Якщо я не можу впоратися з винятком, що я роблю? Нехай він поширює резервну копію стек? Якщо я не розглядаю його, як я можу його зареєструвати і представити зручне повідомлення про помилку. Що більшість людей роблять у веб-програмах та веб-службах?

Як приклад, скажімо, я маю нижчий рівень даних, який тягне дані з sql

try{
  //do something with db
}catch(SqlException ex){
 //what should i do here
 //should i call code again to retry getting data from db
}catch(Exception ex){
 //should i even catch exception of type exception
}

Як вирішити винятки в нижчих ярусах? Чи повинен я просто дозволити виключенням переміщувати яруси? Якщо це так, то, якщо я хочу отримати виняток із типу sqlexception, то мені потрібна посилання на бібліотеку sqlexception є частиною, але, звичайно, мені не доведеться посилатися на цю бібліотеку в шарі, який не має нічого спільного з доступом до даних.

1
Ці інші теми можуть допомогти: stackoverflow.com/questions/2765086/& hellip;
додано Автор Brian Dishaw, джерело
додано Автор Brian Dishaw, джерело

3 Відповіді

Деякі прості основні правила:

  • При обробці винятку потрібно, щоб стан вашої програми точно так само, як і раніше, ніж почався код, який спричинив виняток. Вам знадобиться багато лову й, нарешті, блокує відновлення змінних до початкового стану.

  • Розглянемо лише винятком випадків, якщо це дозволяло програмі продовжувати працювати значущим чином. Наприклад, важко зробити що-небудь корисне, якщо сервер бази даних вимкнений, може також зупинити програму.

  • Якщо вам потрібна людина, щоб вжити коригувальні дії (майже завжди), то будьте впевнені, що вона має достатньо інформації для усунення проблеми. Нехай винятки перемішуються до шару інтерфейсу користувача. Уникайте інтерпретації виключень (наприклад, "Не вдалося оновити базу даних"), відображати точне повідомлення про виключення та стеку сліду.

  • Внесіть обробник для AppDomain.CurrentDomain.UnhandledException і вводьте або відображення значення e.ExceptionObject. Допомагає діагностувати невикористані винятки. І допомагає вам уникати лову у всьому світі.

  • Старі невикористані винятки з хорошим діагнозом краще, ніж один, який спричиняє дестабілізацію програми, тому він створює погані дані або видає інші незв'язані винятки.

2
додано
ви, звичайно, не показуєте трасування стеку користувачів. Хіба це небезпека безпеки !!!!
додано Автор Richard Banks, джерело
Звичайно, ні, про що ти говориш?
додано Автор Hans Passant, джерело

Добре, це буде надто коротким, оскільки це ще рано вранці, але я боровся з цим самим питанням, і ось що я розумію:

"обробляти виключення, які ви можете відновити"

Моє розуміння тут полягає в тому, що ви отримуєте виняток до рівня у своєму коді, де ви можете щось зробити про це. У випадку з кодом низького рівня ви б видалили бульбашковий виняток у шар, де ви можете змінити ваш процес, щоб обробляти виняток, і, можливо, спробуйте процес знову. (Я, як правило, записую помилку прямо там, де вона кинута).

1
додано
@DylanSmith це насправді хороший момент. Я щойно писав код за допомогою цього методу, оскільки у мене різні траси, визначені для різних областей мого коду. Таким чином, журнал записується на відповідний Trace ...
додано Автор Nitax, джерело
Взагалі хороша порада, крім останнього. Якщо ви просто хочете зареєструватися, ви повинні зробити це на максимально можливий рівень (наприклад, користувальницький інтерфейс), інакше ви отримаєте код, який виконує реєстрацію помилок, розкидані по всьому коду. Якщо ви просто перепустіть їх, ви можете мати загальний обробник помилок верхнього рівня, який реєструє будь-які невикористані винятки.
додано Автор Dylan Smith, джерело
Для того, щоб розширити відповідь Nitax, ви, наприклад, не намагаєтеся обробляти OutOfMemoryException, яка викидається, коли система вичерпає пам'ять, ви замість того, щоб збоїти, спробуйте зберегти роботу користувачів та вийти з програми витончено.
додано Автор Security Hound, джерело

Управління винятком - це велика тема, тому я торкаюся лише поверхні тут.

    

З статей ive читається, що "обробляються лише винятки, які ви можете відновити". Що означає це.

  

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

У деяких випадках вам потрібно спіймати винятки, щоб ви могли отримати загальне відновлення, наприклад, скасовуючи або скасовуючи транзакцію. У такому випадку прийнятний підхід - це  спіймайте виняток, виконайте загальне відновлення, а потім знову викиньте виняток.

    

Якщо я не можу розглянути виняток, що я роблю. Нехай він підтримує резервну копію стек?

  

Так.

    

Якщо я не впораюся з ним, я можу його зареєструвати та представити дружнє повідомлення про помилку. Що більшість людей роблять у веб-програмах та веб-службах?

  

Веб-сервер буде зареєструвати виключення. Якщо ви хочете представити дружнє повідомлення про помилку в веб-додатку, ви можете зловити/зареєструватися на найвищому рівні стеків і переспрямовувати до повідомлення про помилку. Знову ж таки, я б намагався не ловити System.Exception - замість цього створіть список виключень, які викидає ваш додаток, і спіймайте лише ці типи, перш ніж представляти повідомлення, адаптоване до кожного типу. Оскільки список типів виключень зростає, або запобігати кожному новому виключенню, змінюючи код, або додати новий вигляд для цього типу виключення.

У веб-службі можна створити власне виключення та додати його як вузол до загального винятку, наданого веб-службою.

У вашому прикладі коду я не буду використовувати try ... catch, якщо ви не очікуєте винятку, і ви знаєте, що з ним робити.

    

Як вирішити винятки на нижчих рівнях. Чи повинен я просто дозволити виключенням переміщати яруси.

  

Так.

1
додано
Дякую за це. дуже прямо вперед. Якщо мені довелося ловити на найвищому рівні в веб-програмі. Який вид винятку я б зловив. Скрізь, де ive читає, станів не ловлять виключення виключення типу
додано Автор Richard Banks, джерело
добре, звучить непогано. Якщо я хочу зловити sqlexception, і я хочу зловити його в інтерфейсі, мені потрібно додати посилання на область імен, що містить тип виключення. Це здається правильним
додано Автор Richard Banks, джерело
@ Річард: Я змінив текст, щоб відповісти на ваш коментар.
додано Автор RoadWarrior, джерело
@Richard: Я не думаю, що довідка збірки (для доступу до простору імен) є великою угодою. Це не роздуває ваш код. У мене, як правило, покладено посилання на управління виключеннями та просторами імен у окремому класі, щоб приховати все і не забруднювати інші класи з випадковими просторами імен.
додано Автор RoadWarrior, джерело
var chat = new Chat();
var chat = new Chat();
642 учасників

Обсуждение вопросов по C# / .NET / .NET Core / .NET Standard / Azure Сообщества-организаторы: — @itkpi — @dncuug