В C # как узнать, какие исключения нужно ловить? - PullRequest
11 голосов
/ 28 апреля 2010

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

Ответы [ 11 ]

18 голосов
/ 28 апреля 2010
  1. Да, за исключением пары очень специфических случаев, это плохая практика. Я могу вспомнить один общий случай, когда перехват всех исключений не является паршивой идеей, когда вы регистрируете сообщение или трассировку стека непосредственно перед тем, как приложение собирается завершить работу (или, может быть, вы регистрируетесь и Повторное выбрасывание).

  2. Поймайте только те исключения, которые, как вы знаете, вы можете обработать. Не больше, не меньше. Если вы не знаете, что из метода может быть сгенерировано исключение, вы все равно не будете обрабатывать его должным образом, поэтому не перехватывайте его. Методы и библиотеки отвечают за документирование исключений, которые вы должны уметь обрабатывать. Кроме того, не перехватывайте исключения, которые указывают на сбой логики, например NullReferenceException и ArgumentException. Они указывают на подлинную ошибку в вашем программном обеспечении, которую вы должны исправить, а не на то, что вы должны устранить во время выполнения.

5 голосов
/ 28 апреля 2010

Да, это плохая практика. Эмпирическое правило: «ловите исключения, на которые вы можете ответить, отпустите другие».

try {
    File.Open(usersChosenFile, FileMode.Open);
} catch(FileNotFoundException) {
    // tell the user the file is gone, give them a chance to respond
    // this is good
} catch(UnauthorizedAccessException) {
    // this is good too
} catch(Exception) {
    // what did you just catch? Who knows. What if its OutOfMemoryException?
    // Do you really want to deal with that here? Let this one go by
}
3 голосов
/ 28 апреля 2010

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

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

Рекомендую несколько ссылок:

2 голосов
/ 28 апреля 2010

Больший вопрос в том, нужно ли вам выполнять конкретную обработку ошибок для определенных исключений. Если вам просто нужно перехватить любые ошибки, нет ничего плохого в том, чтобы просто сделать общий блок try / catch:

try
{
    // Some Code
}
catch
{
}

Однако, если вам нужно выполнить специальную обработку для определенных исключений, вы можете указать несколько блоков catch за одну попытку:

try
{
    // Some Code
}
catch(ArgumentException argE)
{
}
catch(NullReferenceException nullE)
{
}
catch(Exception e)
{
    // Everything else
}

Если вы не можете восстановиться после исключения, не поймайте его на этом уровне.

1 голос
/ 28 апреля 2010

Как сказал Кайл, делайте ваши методы небольшими по длине, ставьте try / catch только на небольших участках. Наведите указатель мыши на методы, которые вы вызываете - вы должны получить список исключений. Это не охватит все перечисленные исключения, но исключения также могут быть обнаружены эмпирически, если вы напечатаете тип исключения внутри вашего catch (Exception e) { ... }. То, что вы ищете, это e.GetType().FullName и e.StackTrace и e.Message и e.InnerException ... или подмножество того, что я перечислил.

1 голос
/ 28 апреля 2010

IMO - не перехватывайте никаких исключений, если только вы не планируете добавить значение к нему и / или оно может быть обработано только этим методом.

Пожалуйста, имейте общий обработчик исключений, который обрабатывает все необработанные исключения.

НТН.

0 голосов
/ 28 апреля 2010

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

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

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

0 голосов
/ 28 апреля 2010

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

Исключение (простите): Стоит иметь что-то на самом верхнем уровне (например, Application.ThreadException или AppDOmain.UnhandledException), чтобы попытаться зарегистрировать те исключения, которые вы не обработали. Если регистрация не удалась, вы все равно обречены.

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

0 голосов
/ 28 апреля 2010

За исключением редких ситуаций, я обычно рассматриваю блоки catch как запах кода.

Предотвратить появление исключений, предварительно проверив условия. Например, при чтении из файла используйте классы в System.IO, чтобы проверить, существует ли файл, вместо использования блока catch для обработки ситуации, когда файл не существует.

Блоки Catch не должны быть частью логики вашего приложения.

0 голосов
/ 28 апреля 2010

В документации часто описываются исключения, которые может вызвать метод, и условия, при которых это может произойти. Это особенно относится к справочной документации Microsoft для платформы .NET.

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

...