Как часто я должен использовать попробовать и поймать в C #? - PullRequest
32 голосов
/ 03 февраля 2009

При написании приложения на C #, приоритет # 1 которого равен , никогда не происходит сбой , как часто мне следует использовать блок try-catch?

Могу ли я инкапсулировать все операторы в методе в блоки try-catch?

public void SomeMethod()
{
    try
    {
        // entire contents of the function
        // library calls
        // function calls
        // variable initialization .. etc
    }
    catch (Exception e)
    {
        // recover
    }
}

Каковы недостатки в упаковке всего в блоки try-catch?

Ответы [ 13 ]

31 голосов
/ 03 февраля 2009

Единственный недостаток - когда на самом деле выдается исключение. Нет никаких накладных расходов для переноса кода, за исключением случаев, когда возникают исключения.

Кроме того, вы не хотите использовать try / catch для управления потоком. Учтите это (плохой код):

try {

    FileStream fs = File.Open("somefile.txt", FileMode.Open);

} catch (Exception ex) {
    MessageBox.Show("The file does not exist. Please select another file");
}

Вы получите больше производительности от таких вещей, как File.Exists. такие как:

if(!File.Exists("somefile.txt"))
  MessageBox.Show("The file does not exist.")

EDIT: нашел прямую цитату MSDN :

Поиск и разработка прочь код с большим количеством исключений может привести к достойная победа Имейте в виду, что это не имеет ничего общего с try / catch блоки: вы платите только тогда, когда фактическое исключение выбрасывается. Вы может использовать столько блоков try / catch, сколько ты хочешь. Использование исключений безвозмездно, где вы теряете спектакль. Например, вы должны держаться подальше от таких вещей, как использование исключения для потока управления.

24 голосов
/ 03 февраля 2009

Это большая тема. Начните здесь , чтобы немного обсудить исключительные методы работы с лучшими практиками и быть готовым к религиозной войне ...

Блог группы анализа кода

Мартин Фаулер - Fail Fast

MSDN при обработке исключений

Проверено против непроверенных исключений

Мое собственное мнение таково, что по большей части вы часто используете «попробуй / наконец», но очень мало «поймай». Проблема в том, что если вы попытаетесь перехватить и обработать исключения в неправильных экземплярах, вы можете непреднамеренно перевести ваше приложение в плохое состояние. Как правило, используйте dev и test, чтобы узнать, где на самом деле нужно обрабатывать исключение. Это будут места, которые вы не можете проверить. то есть вам не нужно обрабатывать нулевую ссылку или файл, не найденный, потому что вы можете предварительно проверить их. Могут случиться только исключения, о которых вы знаете, но вы ничего не можете с этим поделать. Кроме того, ради состояния ваших данных пусть происходит сбой.

Если вы глотаете исключения, это обычно означает, что вы не понимаете свою программу или почему вы получаете исключение. Catching System. Исключением является постер дочернего кода от запахов кода ...

8 голосов
/ 03 февраля 2009

На самом деле, я очень редко использую блок catch, кроме как для регистрации. finally гораздо чаще встречается для меня. В большинстве случаев lock или using делают все, что я могу с пользой (и это действительно finally).

У Эрика Липперта есть запись в блоге об исключениях , которая может быть полезна.

4 голосов
/ 03 февраля 2009

Как правило, IMO лучше помещать более мелкие куски, которые находятся вне вашего контроля, в попытку. Если вы говорите:

try
{
   //anything that could possibly go wrong
   //This kind of thing is only good for Logging IMO and could be done in
   //Global.asax
}

Как вы могли знать, что делать в методе catch, потому что это может быть что угодно ...

Гораздо лучше идти:

try
{
   //divide user imputs
}
catch(DivideByZeroException)
{
  // tell user bad inputs ect....
}
catch (Exception e)
{
    //If you choose to throw the exception you should
    //***********************
    throw; 
    //VS
    throw ex; //Throw ex will restart the stack trace  
    // recover
}
finally
{
    //Clean up resources and continue
}

В котором, наконец, всегда выполняется

3 голосов
/ 03 февраля 2009

Ключом к этому вопросу является следующая строка:

// recover

Чтобы выздороветь, нужно знать, что и как восстанавливать. И это при условии, что можно восстановить, что не так часто.

Вы должны использовать только часть catch в try/catch/finally, чтобы проглотить исключение, когда вы знаете, как обрабатывать исключение, когда вы знаете, как его восстановить, и когда вы уверены, что можете сделать это, не выходя из приложение в несогласованном или недействительном состоянии.

Если вы можете сделать это для всех возможных исключений во всех вызовах методов в вашем приложении, тогда идите вперёд, в противном случае вам может понадобиться переосмыслить ваш приоритет № 1 (иногда неудачный быстрый вариант лучше, чем попытка сохранить приложение жив, когда что-то пошло не так, а потом отладить сбой гораздо труднее).

2 голосов
/ 03 февраля 2009

Вы должны только перехватить и остановить исключение, не выбрасывая его, если вы можете осмысленно обработать его. В противном случае это ошибка, и она должна распространяться вверх.

Я предполагаю, что когда они говорят, что "это приложение никогда не должно падать", существует неявное требование, что оно ведет себя правильно. Только остановка исключений, которые обрабатываются осмысленно, удовлетворяет требованию правильного поведения.

Как правило, в приложении будет один блок catch верхнего уровня для перехвата и регистрации необработанных исключений. Это должно происходить редко (и, возможно, ваше требование может быть истолковано как означающее, что это не должно происходить вообще). Если вы поймаете и остановите исключения в другом месте своего кода, вы рискуете не обнаружить эти проблемы. Если вы перехватываете журнал и останавливаетесь во многих других частях своего кода, у вас плохое приложение с точки зрения разделения проблем.

1 голос
/ 01 февраля 2018

Я стараюсь вообще избегать try catch блоков. Я предпочитаю использовать циклы, чтобы заставить пользователя подчиняться правилам приложения. Например, если пользователь должен ввести только int, равное или меньшее, чем int x, я бы использовал:

if (input > x)
{
     Console.WriteLine("Invalid input. Please enter a number that is equal to or less than x.");
{...}
}

вместо использования:

catch (IndexOutOfRangeException)
{
      //error message here
}

Исходя из моего личного опыта, мне легче писать, так как вы можете избежать инкапсуляции кода в блоке try (защитный код).

Конечно, всегда будет время, когда использование try catch неизбежно - мне просто нравится обходить его везде, где это возможно.

1 голос
/ 03 февраля 2009

Вы можете сделать это, хотя почти в любой конкретной среде, в которой вы работаете, есть глобальный обработчик исключений, где вы можете перехватывать и обрабатывать даже неизвестные ошибки.

Для веб-приложений есть Global.asax, для консольной программы просто оберните свой Main () в try / catch, для служб есть AppDomain.CurrentDomain.UnhandledException и т. Д.

Вам следует заключить разделы, в которых вы можете предсказать, каким может быть исключение, в более конкретные блоки, но глобальные обработчики исключений должны значительно упростить ваш код и помочь вам.

1 голос
/ 03 февраля 2009

Производительность для блоков try возрастает, если вы делаете так, что вся ваша функция будет работать медленнее, чем в противном случае. catch (Exception e) также плохая идея, если вы поймете, что хотите сделать что-то полезное с тем, что вы поймали, и если вы поймаете все исключения, невозможно узнать, что вы должны делать.

0 голосов
/ 10 февраля 2014
public void functionName  
{
  try
  {
     //your codes
     //sometimes 'return' shows exceptions
  }
  catch(Exception e)
  {
    messagebox.show(e.Tostring());   //to know what is the exception
  }
  finally
  {
  }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...