Коли в іменах методу C # слід використовувати "Спробуйте"?


180

Ми обговорювали з нашими колегами про те, що це означає, якщо назва методу починається з "Спробувати".

Існували такі думки:

  • Використовуйте "Спробувати", коли метод може повернути нульове значення.
  • Використовуйте "Спробувати", коли метод не викине виключення.

Яке офіційне визначення? Що означає "Спробуйте" у назві методу? Чи існує якесь офіційне керівництво щодо цього?


83
+1 Люди, які так багато роздумували над іменами своїх функцій, насправді шукають "наступного хлопця". Не впевнений, чому це наближення голосів (і це йде від хлопця, який сьогодні багато кинув їх.)
Джонатан Райнхарт

7
@JonathonReinhart, він отримав близькі голоси, тому що "Наразі це питання не підходить для нашого формату запитань і запитань. Ми очікуємо, що відповіді будуть підкріплені фактами, посиланнями або конкретною експертизою, але це питання, ймовірно, вимагає дискусій, аргументів. , опитування чи розширене обговорення ".
Пранів Хосангаді

16
Там є офіційна заява Microsoft , що відповідає на питання (див моя відповідь). Як це не факт?
Ерік Щербум

6
@PranavHosangadi, як згадував Ерік, це підтверджується фактами. Крім того, тут є багато досвідчених розробників C #, які мають певний досвід, щоб дати вагому відповідь. Ерік Ліпперт - головний архітектор мови C #. Я думаю, ви можете назвати цю конкретну експертизу .
Джонатан Райнхарт

4
@ErikSchierboom Про те, що це керівництво для MS - це факт. Про те, що керівництво MS - це правильне керівництво для використання, є суб'єктивним та дискусійним.
Сервіс

Відповіді:


148

Ця модель відома як модель TryParse і була задокументована Microsoft. На офіційній сторінці MSDN про винятки та ефективність сказано :

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

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


2
Ще одне корисне посилання, яке документує цей зразок (пошук у TryParse) blogs.msdn.com/b/kcwalina/archive/2005/03/16/396787.aspx
Vivek Maharajh

2
В основному, якщо у вас є метод TryParse, у вас повинен бути метод Parse, який видає, коли TryParse поверне помилковим. І навпаки, якщо у вас є метод Parse, ви повинні розглянути можливість TryParse-методу, який поверне помилковим, коли Parse кине
3Doubloons

5
+1. Додамо лише до цього, винятки, як правило, стосуються "виняткових" обставин. Якщо ви робите щось, що може легко вийти з ладу, і цей збій не особливо помітний, то використання цієї моделі є більш ідіоматичним, ніж спроба / ловити
Адам Робінсон

Чи справді така схема вимагала вказівки від Microsoft? Здається, досить базові речі.
Дейв Лоуренс

19
Це є основним матеріалом, але це зовсім не означає , що рекомендації не є корисними. Правильне отримання базових речей може бути досить важким, якщо ви не знаєте платформи досить добре.
Erik Schierboom

119

(Виправлено) Є офіційна інструкція, як запропонував Ерік.

Коли я бачу TrySomethingметод, я припускаю його

  • не кидає
  • повертає bool
  • якщо я очікую значення, воно повертається через параметр 'out'
  • існує Somethingметод, який дозволяє мені самостійно впоратися з будь-яким винятком. (редагувати, запропонував Джессі Вебб)

4
Виправлення - має офіційне керівництво. Дивіться відповідь Еріка.
nothrow

8
+1 Але я також маю четверте сподівання: якщо є TryFooметод, буде подібний Fooметод, який дозволяє мені самостійно обробляти будь-які винятки. Підписи цих методів, ймовірно, будуть різними, тому їх використання не буде взаємозамінним без інших змін коду.
Джессі Вебб

1
@JesseWebb, дякую, що вказали на це. Я додав ваш коментар у свою відповідь, якщо ви не заперечуєте.
nothrow

1
"Не кидає" мені здається переродженим. Наприклад, Int32.TryParse (String, NumberStyles, IFormatProvider, Int32) викидає ArgumentException, якщо йому не подобається параметр стилю.
Jirka Hanika

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

8

Я думаю, ви повинні використовувати, tryколи хочете продовжити. Не має значення, метод повертає якесь значення чи ні.

Випадок 1: якщо він повернеться нормально, ви можете продовжити певним чином.

Випадок 2: якщо воно не повертається: воно все одно добре; можна продовжувати інакше.

І якщо ви очікуєте деяке значення як вихід цього методу, тоді використовуйте outпараметр.

Приклад

int value
if (dictionary.TryGetValue("key", out value))
{
    // Proceed in some way
}
else
{
    // Proceed in some other way
}

6

Ви повинні використовувати "Спробувати" у назві методу, коли ви хочете виявити факт, що виклик методу може давати недійсний результат. Дотримуючись стандарту .NET, це, до речі, не функція, яка викликає виняток, а функція, яка повертає деяке VALIDабо NON_VALID, з точки зору програми, значення.

Зрештою, це все про конвенцію про іменування, яку ви вирішили використовувати у своїй групі.


5

Обов’язково вкажіть tryу своєму імені методу, якщо:

  • ви не кидаєте жодного винятку
  • ваш метод має такий підпис: bool TrySomething(input, out yourReturn)

Отже, якщо ми використовуємо try-методи, ми отримуємо лише булевий результат.

Отже, наступний код не викидає жодних винятків:

string input = "blabla";
int number;
if (int.TryParse(input, out number))
{
// wooohooo we got an int!
} else
{
//dooh!
}

Тоді як цей код може (і в цьому випадку буде) викидати винятки:

string input = "blabla";
int number;
try
{
     number = int.Parse(input); //throws an exception
}
catch (Exception)
{
     //dooh!
}

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


Ваш фрагмент коду №2 повинен читати, int number = int.Parse(input);якщо ви хочете, щоб він був більш значимим у цьому контексті.
П’єр Арно

@PierreArnaud Дякую, змінив це!
Фабіан Біглер

Ви все ще не вистачаєте int number;декларації перед блоком спробу та number = ...призначенням.
П’єр Арно

@PierreArnaud Дякую, я також включив "int number" зараз.
Фабіан Біглер

Зауважте, що ви все одно можете викидати винятки, якщо виняток дещо не пов'язаний з прямою дією, яка виконується, наприклад, TryLoadFile(path, out file)woah, з оперативної пам'яті. Таким чином, абонент очікував би не помилок за поганий шлях або відмову в доступі, а виняток для химерних речей, які також можуть піти не так. І документуйте це.
Люк Пуплетт

0

Дядько Боб наводить приклад нижче у своїй книзі « Чистий код» . Щоразу, коли ми очікуємо, що виняток буде видалено, ми можемо використовувати Tryпрефікс до назви методу:

public void sendShutDown()
{
    try{
        tryToShutDown();
    } catch (DeviceShutDownError e) {
        logger.log(e);            
    }
}

А потім (адаптовано):

private void tryToShutDown()
{
    //some code with no error handling, but
    //something might go wrong here
}

tryToShutDownМетод не робить ніякої обробки помилок, тому що це відповідальність sendShutDownметоди.

TryParseМодель Microsoft порушує чистий код директиву , яка говорить , що ми повинні уникати вихідних параметрів.

Якщо ми не розробляємо нову версію C #, нам не доведеться дотримуватися всіх інструкцій Microsoft. Іноді вони не найкращі.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.