Где правильное место для обработки исключений в моих приложениях C #? - PullRequest
5 голосов
/ 23 ноября 2011

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

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

Теперь большинство моих методов в моих вспомогательных классах либо делают HttpWebRequest, либо выполняютоперации сохранения / удаления файлов.Сказав, что мне нужно учесть вероятность того, что в конечном итоге вызов не будет завершен, или файл не может быть сохранен, потому что не хватает места или что-то еще.Проблема, с которой я сталкиваюсь, заключается в том, что мне приходится писать операторы try / catch каждый раз, когда я вызываю один из методов.Кроме того, я должен перепечатать сообщение об ошибке (или, в конце концов, сообщение о состоянии. Я хотел бы знать, когда оно также будет успешным).

Итак, вот своего рода фрагмент того, что я должен напечатать:

  try
  {
     ItemManager.SaveTextPost(myPostItem);
  }
  // Majority of the time there is more than one catch!
  catch
  {
     //^^^Not to mention that I have to handle multiple types of exceptions 
     //in order to log them correctly(more catches..ugh!)
     MessageBox.Show("There was an error saving the post.");
     //Perform logging here as well
  }

Из того, что я до сих пор сделал вывод:

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

Правильный ли этот подход?Есть ли другой способ сделать это?Должен ли я использовать try / catch в вызывающем методе вообще?Так как это мой первый выстрел, мне бы очень хотелось услышать, что скажут другие, кто занимался этим сценарием.

Ответы [ 7 ]

1 голос
/ 23 ноября 2011

Try / Catch - хорошее решение.Одно из предложений, мне нравится использовать это, чтобы остановить поток ошибок: перехват исключений: try {} catch (Exception ex) {ShowExceptionError (ex);} Затем я просто скину все исключения в один метод и позволю методу обрабатывать каждое из них.

Вроде как:

1 голос
/ 23 ноября 2011

Все эти способы являются отличными вариантами. Одна вещь, которую вы не хотите делать, - это использовать try {} catch {} для управления потоком. Это означает что-то вроде этого (снова избегайте этого)

Void SomeMethod()
{
     try
     {
         while(somecondition)
         {
             try
             {
             }
             catch (Exception ex)
             {

             }
          }
     }
     catch (Exception ex)
     {
          .....
     }

Вместо этого вы хотите защищаться.

1 голос
/ 23 ноября 2011

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

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

try
{
   ItemManager.SaveTextPost(myPostItem);
   // SaveTextPost can throw some exceptions (that you know)
}
catch (Exception e)
{
   // You know the exceptions that SaveTextPost can return, so threat them 
   // correctly
   if (e is FileNotFoundException)
       MessageBox.Show("The file was not found when saving the post.");
   else if (e is ArgumentNullException)
       MessageBox.Show("The post can't be null to be saved.");
   else
       MessageBox.Show("There was an error saving the post.");
}

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

1 голос
/ 23 ноября 2011

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

1 голос
/ 23 ноября 2011

Я думаю, что поместить try / catch в метод, который вы вызываете, совершенно нормально. Вы можете вернуть коды ошибки / успеха в вызывающий код различными способами. .NET и c # хорошо обрабатывают перечисления, поэтому вы можете иметь ItemManager.SaveTextPost(myPostItem, out errorCode);, где errorCode будет перечисляемым значением, которое сообщит вам, если возникнут какие-либо проблемы. Это также может быть так же просто, как если бы метод вернул bool true в случае успеха, false в противном случае. Есть много способов справиться с этой проблемой, но, насколько мне известно, использование метода try / catch является предпочтительным способом выполнения действий.

1 голос
/ 23 ноября 2011

AOP библиотеки, такие как PostSharp , предназначены для решения сквозных задач в точности так.

Если все эти вспомогательные методы используют один и тот же шаблонный пример try catch -> обрабатывают несколько типов исключений, вы можете написать один аспект, который это делает, и украсить все соответствующие методы соответствующим атрибутом.

0 голосов
/ 23 ноября 2011

Мой личный взгляд на обработку исключений - добавить try {} catch {}, где это имеет смысл.

Например, всегда используйте try catch при вызове «ненадежного» кода, то есть модулей или плагинов. иначе, если вы собираетесь поймать исключение, убедитесь, что вы можете сделать что-то значимое с ним. Если нет, позвольте исключению вспыхнуть до точки, где вы можете.

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

...