C # попробуйте поймать шаблон справки - PullRequest
10 голосов
/ 24 февраля 2011

Нам всегда нужно пытаться поймать наш код, и он становится ужасным, как

public void foo()
{
  try
  {
    DoSomething();
  }
  catch(Exception e)
  {
     //do whatever with e
  }
}

public int FooReturnInt()
{
  try
  {
     return IntAfterSomeCalculation();
  }
  catch(Exception e)
  {
    //do exactly whatever with e as foo()
  }
}

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

В идеале, поскольку часть try catch идентична, и мы можем передать Func <> в качестве параметра вспомогательной функции, которая выполняет что-то вроде

public void TryCatch(Func<something> theFunction)
{
  try
  {
    theFunction();
  }
  catch(Exception e)
  {
    //processthe common exception        
  }
}

Тогда я представляю, что это приведёт в порядок мой код, теперь проблема в том, как правильно написать эту функцию? Тип возврата этой функции зависит от типа возврата функции.

Ответы [ 5 ]

20 голосов
/ 24 февраля 2011

Если вы действительно думаете, что это необходимо, вы можете использовать:

public T TryCatch<T>(Func<T> theFunction)
{
  try
  {
    return theFunction();
  }
  catch(Exception e)
  {
    // You'll need to either rethrow here, or return default(T) etc
  }
}

Однако я бы вообще советовал против этого.Вы действительно уверены , что вам нужны блоки try / catch во всех этих методах?Как правило, в не должно быть множества блоков try / catch, если только catch не оборачивает исключение и не перебрасывает ... и даже в C # это реже, чем в Java, например.

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

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

8 голосов
/ 24 февраля 2011

Существует три причины для использования блока catch:

1 Потому что может быть исключение.

Это неправильная причина.

2 Потому что выможет как-то обработать исключение.

Это правильная причина.

3 Поскольку вы хотите добавить и / или скрыть детали

Этот catch & wrap включает повторный бросок и на самом деле не является уловкой.

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

7 голосов
/ 24 февраля 2011

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

Механизм исключений try / catch был разработан, чтобы освободить разработчиковот необходимости связывать коды возврата изнутри кода, позволяя исключениям «фильтровать» стек вызовов, пока не будет найден обработчик.(Единственное время, когда вы видите исключение, это когда оно не обрабатывается каким-либо методом в цепочке вызовов.) В любом случае, вот вам достойное место для начала по этой теме .

А здесь "правила большого пальца" поста в блоге, который будет легче переварить, чем статья MSDN.И еще одна ссылка с еще более сокращенным содержанием.

Выдержка из предыдущей ссылки:

  1. Не перехватывайте исключения, которые выне может обработать
  2. Никогда не глотать исключения
  3. В вашем коде должно быть больше Try / Наконец (или использование), чем Try / Catch
  4. Никогда не выбрасывайте / ловите новое Exception () (слишком широкий класс) вместо этого попытайтесь отбросить \ поймать более производное исключение (ArgumentNullException и т. д.)
  5. При повторном вызове исключения используйте throw;в отличие от броска бывших;это предотвратит сброс трассировки стека
  6. При написании библиотеки и приложения я никогда не улавливаю ожидание, если не смогу ТОЧНО обработать его
  7. Использовать логику для управления потоком программычем исключения, проверьте на NULL, а не поймайте ArgumentNullException

Номер 6 применяется в вашей ситуации напрямую.

0 голосов
/ 24 февраля 2011

Вам действительно нужно отлавливать исключения в каждом методе? Это нормально, если метод генерирует исключение, если оно обрабатывается «где-то».

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

0 голосов
/ 24 февраля 2011

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

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

...