Наилучшая практика обработки исключений в приложении Windows Forms? - PullRequest
117 голосов
/ 08 октября 2008

В настоящее время я пишу свое первое приложение для Windows Forms. Сейчас я прочитал несколько книг по C #, поэтому у меня есть относительно хорошее понимание того, какие функции языка C имеют дело с исключениями. Однако все они довольно теоретичны, поэтому у меня пока нет ощущения, как преобразовать базовые концепции в хорошую модель обработки исключений в моем приложении.

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

Основные вещи, которые я сейчас пытаюсь решить:

  • Когда мне повторно выдать исключение?
  • Должен ли я попытаться иметь какой-то центральный механизм обработки ошибок?
  • Имеет ли обработка исключений, которые могут быть сгенерированы, снижение производительности по сравнению с упреждающим тестированием, например, существует ли файл на диске?
  • Должен ли весь исполняемый код быть заключен в блоки try-catch-finally?
  • Есть ли случаи, когда пустой блок catch может быть приемлемым?

Все советы с благодарностью получены!

Ответы [ 16 ]

1 голос
/ 15 марта 2009

Я полностью согласен с правилом:

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

Причина в том, что:

  • Когда вы впервые записываете код, скорее всего, вы не будете в полной мере знакомы с 3-сторонним кодом, библиотекой .NET FCL или последними публикациями ваших коллег. На самом деле вы не можете отказаться от написания кода, пока не будете хорошо знать все возможные исключения. Так
  • Я постоянно нахожу, что использую try / catch (Exception ex) только потому, что хочу защитить себя от неизвестных вещей, и, как вы заметили, я ловлю Exception, а не более конкретные, такие как OutOfMemoryException и т. Д. И я всегда сделать исключение, которое выдается мне (или QA) ForceAssert.AlwaysAssert (false, ex.ToString ());

ForceAssert.AlwaysAssert - мой личный способ Trace.Assert, независимо от того, Макрос DEBUG / TRACE определен.

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

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

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

Для кода WinForms я всегда соблюдаю золотое правило:

  • Всегда пытайтесь / ловите (Исключение) код вашего обработчика события

это защитит ваш пользовательский интерфейс от возможности его использования.

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

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

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

В моем опыте я сочла целесообразным ловить исключения, когда я знаю, что собираюсь их создавать. В тех случаях, когда я нахожусь в веб-приложении и выполняю Response.Redirect, я знаю, что получу исключение System.ThreadAbortException. Так как это преднамеренно, я просто ловлю определенный тип и просто проглатываю его.

try
{
/*Doing stuff that may cause an exception*/
Response.Redirect("http:\\www.somewhereelse.com");
}
catch (ThreadAbortException tex){/*Ignore*/}
catch (Exception ex){/*HandleException*/}
1 голос
/ 08 октября 2008

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

Try
{
int a = 10 / 0;
}
catch(exception e){
//error logging
throw;
}

выполнение этого приведет к завершению трассировки стека в операторе catch. (избегайте этого)

catch(Exception e)
// logging
throw e;
}
1 голос
/ 08 октября 2008

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

Я использовал пустые блоки catch в местах, где пользователь может сделать что-то, что на самом деле не является «неправильным», но может вызвать исключение ... пример, который приходит на ум, - это GridView, если пользователь DoubleCLicks серый заполнитель ячейки в верхнем левом углу, он будет запускать событие CellDoubleClick , но ячейка не принадлежит ряду. В этом случае вам не нужно действительно нужно опубликовать сообщение, но если вы его не перехватите, оно выдаст пользователю необработанную ошибку исключения.

1 голос
/ 08 октября 2008

Когда мне повторно выдать исключение?

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

Должен ли я иметь какой-то центральный механизм обработки ошибок?

Я пишу файл журнала ... довольно просто для приложения WinForm

Имеет ли обработка исключений, которые могут быть сгенерированы, снижение производительности по сравнению с упреждающим тестированием, например, существует ли файл на диске?

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

Должен ли весь исполняемый код быть заключен в блоки try-catch-finally?

Yeap

Есть ли случаи, когда пустой блок улова может быть приемлемым?

Да, допустим, вы хотите показать дату, но вы не знаете, как эта дата хранилась (дд / мм / гггг, мм / дд / гггг и т. Д.), Вы пытаетесь ее проанализировать, но если она не удалась, просто сохраните собирается ... если это не имеет отношения к тебе ... я бы сказал, да, есть

0 голосов
/ 14 марта 2017

Вы должны думать о пользователе. Сбой приложения - это последняя вещь, которую хочет пользователь. Поэтому любая операция, которая может дать сбой, должна иметь блок try catch на уровне пользовательского интерфейса. Не обязательно использовать try catch в каждом методе, но каждый раз, когда пользователь что-то делает, он должен иметь возможность обрабатывать общие исключения. Это никоим образом не освобождает вас от проверки всего для предотвращения исключений в первом случае, но нет сложного приложения без ошибок, и ОС может легко добавить непредвиденные проблемы, поэтому вы должны предвидеть неожиданные и убедиться, что пользователь хочет их использовать. операция не будет потери данных, потому что приложение вылетает. Нет необходимости позволять сбою вашего приложения, если вы перехватываете исключения, оно никогда не будет находиться в неопределенном состоянии, и пользователь ВСЕГДА не испытывает затруднений из-за сбоя. Даже если исключение находится на самом верхнем уровне, отсутствие сбоя означает, что пользователь может быстро воспроизвести исключение или, по крайней мере, записать сообщение об ошибке и, следовательно, значительно помочь вам решить проблему. Конечно, гораздо больше, чем просто получить сообщение об ошибке, а затем увидеть только диалог ошибки Windows или что-то в этом роде.

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

Как пользователь, я, конечно, серьезно разозлился, когда брови, офисное приложение или что-то не работает. Если исключение настолько велико, что приложение не может продолжить работу, лучше отобразить это сообщение и сообщить пользователю, что делать (перезапустить, исправить некоторые настройки ОС, сообщить об ошибке и т. Д.), Чем просто завершить работу и все.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...