Спробуйте Catch або If виписку?

якщо ви вважаєте, що існує можливість отримати виняток із нульовим покажчиком, чи слід використовувати вказівку if, щоб переконатися, що змінна не є нульовою, або ж ви повинні просто отримати виняток?

Я не бачу жодної різниці, оскільки ви можете поставити вашу логіку для роботи з нульовим покажчиком в операторі if або в блоці лову, то з кого це найкраща практика?

21
додано Автор jk., джерело
Основна проблема полягає в тому, що, коли викидається Exception , він буде (спробувати) отримати трасування стека, яка буде використовувати багато часу .
додано Автор Alvin Wong, джерело
виняток є те, що не повинно відбуватися часто, за визначенням. Якщо нуль є можливістю за допомогою вашого потоку, ви не повинні дозволяти це викликати виняток.
додано Автор Karthik T, джерело
Це залежить від того, якщо ви справите загальне виключення
додано Автор Amit, джерело
ловлячи винятки набагато повільніше, ніж якщо .. ще
додано Автор Dmitry Bychenko, джерело
Пов'язані: Коли правильно використовувати обробку виключень для бізнес-логіки?моя відповідь на це питання , що, до речі, разом з прикладом у питанні ілюструє, що ускладнює вирішення винятків у таких випадках).
додано Автор Michael Kjörling, джерело
додано Автор argaz, джерело

10 Відповіді

Я б сказав: ЗАВЖДИ використовуйте логіку, щоб спіймати виняток, а не спробувати/ловити.

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

36
додано
Просто для того, щоб додати до цього, я думаю, що підказка в назві - виняток, який ви зловите - це лише виняток із потоку вашого коду, який ви не могли спрогнозувати або не зможете виконати. Якщо логіка може впоратися з цим, це не виняток.
додано Автор CeejeeB, джерело

Немає єдиної відповіді, яка буде достатньою тут, це залежить .

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

Сценарій: метод, який приймає параметр типового посилання, який не приймає null

Ви визначаєте метод, він приймає параметр типового типу, скажімо, потік об'єкта, і ви не хочете приймати null як законний параметр введення.

У цьому випадку я б сказав, що контракт означає, що null не є дійсним вводом. Якщо якийсь код насправді називає цей метод посиланням null , контракт порушений.

Це виняток, точніше, це ArgumentNullException .

Приклад:

public void Write(Stream stream)
{
    if (stream == null)
        throw new ArgumentNullException("stream");
    ...

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

Q. Чому я не можу повернути false , а не викидати виняток?

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

Сценарій: метод повертає посилання на об'єкт, інколи його немає

У цьому випадку контракт полягає в тому, що null є законним результатом. На мій погляд, null є щось, щоб уникнути, тому що важко переконатися, що ви правильно обробляєте скрізь, але іноді це найкращий спосіб.

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

Узагальнення

Якщо ви уважно поглянете на два вищезазначених сценарії, ви відзначите одне:

В обох випадках це зводиться до очікуваного, що таке контракт .

Якщо в договорі говориться "не null ", викиньте виняток. Не повертайтеся до старого способу API, щоб повернути false , оскільки виняткові проблеми не слід ігнорувати без затримки, а також заповнювати код за допомогою команд if для забезпечення кожного методу дзвінок успішно не робить для читання коду.

Якщо в контракті сказано, що " null цілком можливо", обробіть це з if statements.

Реклама

Для кращого зчеплення з проблемами null я також настійно закликаю вас отримати ReSharper для вас і Ваша команда, але будь ласка, зверніть увагу, що ця відповідь може бути застосована до будь-якого типу винятків та обробки помилок, застосовуються ті ж принципи.

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

public void Write([NotNull] Stream stream)

[CanBeNull]
public SomeObject GetSomeObject()

Щоб дізнатись більше про атрибути контракту, що використовує ReSharper, див

17
додано
Див. Додаткову інформацію про анотації про контракти, доступні в ReSharper тут - введення в контракти атрибутів resharper та тут - доповнення до атрибутів контракту в ReSharper 7 .
додано Автор Lasse Vågsæther Karl, джерело
+1 за відмінне пояснення за сценаріями. Та thx для R # tip. Той був новим для мене.
додано Автор Koen, джерело
Дякую. Безумовно варто почитати.
додано Автор Koen, джерело

Добре. Істотні винятки. Винятки. Вони кидаються, коли відбувається щось непередбачене і не повинно бути частиною звичайного потоку програм.

І ось що відбувається тут. Ви очікували, що аргумент буде вказано, коли це не так. Це несподівано, і ви повинні викинути власне виключення, інформуючи користувача про це. Якщо ви хочете отримати бонусні очки, ви також можете вказати причину, ЧОМУ аргумент повинен бути вказаний (якщо це не є очевидним).

I've written a series of posts about exceptions: http://blog.gauffin.org/2013/04/what-is-exceptions/

4
додано
Логіколог не суперечить собі. Спочатку він каже, що він завжди використовує логіку, і тоді цей спроба/ловля може бути використаний. Якщо ви прочитаєте мою серію статей, ви побачите, що спроба/вилучення рідко може використовуватися для порятунку ситуації.
додано Автор jgauffin, джерело
це суперечить вищезазначеному посту логіолога
додано Автор Backwards_Dave, джерело
Перевага використання логіки для перевірки нульової довідки - ви можете виключити значуще . NullReferenceException є недоліком мого існування при налагодженні. Стік дзвінків повідомляє вам, де слід почати, але не розповідає вам, який з 10 типів реферування є нульовим. Бажаємо, щоб ми мали синтаксис variableName! для підтримуваного компілятора "не nulls". Але, як правило, я залишаю виключення, щоб кинути, і я використовую лише try-catch , якщо я можу обробляти потенційним винятком. Як я вже сказав, нульові посилання можуть скористатися логікою, ніж очікування винятку, оскільки ви можете викинути свій власний.
додано Автор Adam Houldsworth, джерело

З точки зору продуктивності це насправді залежить від того, що ви робите. Ефект продуктивності від блоку try/catch, коли виключення не виключено, є мінімальним (і якщо вам дійсно потрібно, що останні кілька відсотків продуктивності, ви, ймовірно, повинні переписати цю частину вашого коду в C ++). Виключення з винятком впливають на прості операції, такі як маніпулювання рядками; але як тільки ви отримаєте операції з файлами/базами в циклі, вони набагато повільні, що знову стає тривіальним штрафом. Переміщення через домен App матиме нетривіальний вплив на щось що завгодно.

Продуктивність в операціях/секунда:

Mode/operation               Empty   String      File   Database    Complex
No exception            17,748,206  267,300     2,461   877         239
Catch without exception 15,415,757  261,456     2,476   871         236
Throw                      103,456   68,952     2,236   864         236
Rethrow original            53,481   41,889     2,324   852         230
Throw across AppDomain       3,073    2,942       930   574         160

Додаткові результати тесту разом із джерелом для тестів доступні в статті Експлуатаційні наслідки винятків у .NET

3
додано

Його завжди краще використовувати Спробувати зловити , відмінний від , якщо ще Тут Винятки складаються з двох типів, зокрема оброблених та оброблених UN винятків Навіть якщо ви хочете обробляти деяку функцію, коли виключення ви можете впоратися з ним ...

Виняток, що обробляється, завжди дозволяє писати деякі реалізації всередині блоку Catch Напр. Повідомлення попередження, нова функція для обробки при виникненні такого винятку.

2
додано
Я не погоджуюсь. Використання виключень для лову нулів, отримання невірного індексу масиву, поділу на нуль та інші досить поширені ситуації, на мою думку, не є гарною ідеєю.
додано Автор Dariusz, джерело

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

string name = null;

Тут я збираюся використовувати змінну імені, і я впевнений, що це буде кидати Null Revert Error.

try
{
Console.writeLine("Name ={0}",name);
}
catch (NullRefranceException nex)
{
//handle the error 
}
catch(Exception ex)
{
//handle error to prevent application being crashed. 
}

Це не найкраща практика, коли ви можете справити таку помилку та зробити ваш код більш читабельним. люблю.

if(name !=null)
    Console.writeLine("Name ={0}",name);
0
додано

За моїм досвідом використання if краще, але тільки якщо ви насправді очікуєте нульовим посиланням. Без будь-якого коду чи контексту важко сказати, коли один з варіантів краще, ніж інший.

Також є питання оптимізації - блоки try-catch блокують не будуть оптимізовані .

0
додано

Головне питання полягає в тому, якщо це гарна ідея мати методи, які взагалі повертають нуль, особисто у мене немає проблем з цим, але як тільки ви намагаєтеся отримати доступ до модифікаторів об'єкта, повернутого з цього методу, і ви забудете перевірити, чи це призначено це стає проблемою.

Кен має хорошу відповідь про це :

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

     

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

Див цю дискусію в цій проблемі:

Повернення нуля зазвичай є найкращою ідеєю, якщо ви маєте намір це вказати   Немає даних.

     

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

     

Крім того, повернення нуля призведе до виняткового винятку, якщо ви   спроба доступу до учасників об'єкта, що може бути корисним для   підсвічування баг-коду - спроба доступу до члену нічого   не має сенсу. Доступ до членів порожнього об'єкта не збігатиметься   Це означає, що помилки можуть бути невідкриті.

Деякі подальші читання:

0
додано

Я б краще запропонував вам використовувати if-statement для винятку NullReference . Для іншого винятку, try-catch має бути досить гарним.

Причиною я пропоную виняток if-statement для NullReference , тому що C# не буде вказати, яка змінна нульова. якщо в цій лінії більше одного об'єкта може бути нуль, ви втратите слід. Якщо ви використовуєте if-statement , ви можете краще вести журнали, щоб допомогти вам отримати достатньо інформації.

0
додано

Загалом, блоки try-catch чудово, тому що вони розбиваються (переміщуються до звіту про вилов), коли виникає виняток. Якщо ще, блоки покладаються на те, що ви прогнозуєте, коли станеться помилка.

Крім того, блокування зловмисників не зупинить ваш код при припиненні помилки.

0
додано
var chat = new Chat();
var chat = new Chat();
642 учасників

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