Попробуй Наконец или Попробуй Поймать Окончательно

#c# #exception-handling

#c# #исключение

Вопрос:

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

 private ClassInstance GetMeANumber()
{
     Resource a = null;

      try
      {
          Resource a = new Resource();
          return a.GetClassInstance();
      }
      catch
      {
          throw;
      }
      finally
      {
          if(a != null)
              a.Dispose();
      }
}
  

Комментарии:

1. Когда вы в чем-то не уверены, просто проверьте это. Вот так: попробуйте{создать новое исключение();}finally{/* точка останова или консоль. Написать или что угодно */}

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

Ответ №1:

Да, это было бы точно так же.

Однако более распространенным шаблоном является реализация IDisposable на Resource . Затем вы можете использовать using для достижения того же результата более кратко.

 using (Resource a = new Resource()) {
    return a.GetClassInstance();
}
  

Комментарии:

1. Я просто собирался задать вопрос о блоке using. Спасибо.

2. у вас отсутствует функция () при вызове конструктора для ресурса 🙂

3. @forsvarir StackOverflow нужен интегрированный компилятор, чтобы перехватывать подобные вещи 😉

Ответ №2:

Блок захвата «просто перестроить» будет иметь несколько эффектов, которые вам могут понравиться, а могут и не понравиться:

  1. Если трассировка стека включает номера строк, номер строки, связанный с процедурой, которая перехватывает и повторно обрабатывает, будет номером строки повторного выполнения, а не номером строки вызова метода, в котором произошло исключение. В некоторых случаях это может быть очень раздражающим.
  2. Все неявные или явные вложенные блоки «finally» будут выполняться до того, как обработка исключений первого прохода просканирует стек, т.е. до:
    1. Любые внешние блоки фильтров получают шанс на запуск
    2. Отладчик обнаруживает, что исключение в конечном счете не будет обработано
    3. Внешняя область имеет шанс обнаружить, что исключение в конечном итоге не будет обработано, и завершить работу приложения без запуска вложенных блоков «finally».
  3. Если отладчик настроен на перехватывание необработанных исключений, он будет перехватывать в месте повторного переброса, а не в том месте, где произошло исключение.

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

Ответ №3:

Просто для интереса, шаблон кода, который вы опубликовали, в значительной степени соответствует тому, во что превратился бы блок using. Таким образом, ваш код может быть переписан как;

 private ClassInstance GetMeANumber()
{
    using (var a = new Resource())
    {
        return a.GetClassInstance();
    }
}