В C#, как узнать, какие исключения поймать?

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

11 ответов


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

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


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

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
}

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

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

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


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

try
{
    // Some Code
}
catch
{
}

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

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

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


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

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

HTH.


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


при использовании методов framework вы можете проверить документацию MSDN. Каждое описание метода содержит список потенциально создаваемых исключений.

в качестве примера проверьте пункт исключения на .Open () документация.

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


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

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


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

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

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


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

исключение (pardon): стоит иметь что-то на самом верху уровень (например, применение.Threadexceptionметод или AppDomain.UnhandledException), чтобы попытаться зарегистрировать те исключения, которые вы не обработали. Если ведение журнала не удастся, вы все равно обречены.

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


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

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

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