Зачем ловить и отбрасывать исключение в C #?

, если у вас установлен APEX, функция APEX_UTIL.string_to_table делает именно это.

512
задан Community 23 May 2017 в 12:10
поделиться

12 ответов

Первый; то, как это делает код в статье, - зло. throw ex сбросит стек вызовов в исключении до точки, в которой находится этот оператор throw; потеря информации о том, где на самом деле было создано исключение.

Во-вторых, если вы просто поймаете и повторно выбросите вот так, я не вижу никакой дополнительной ценности, приведенный выше пример кода будет таким же хорошим (или, учитывая throw ex bit, даже лучше) без try-catch.

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

try 
{
    // code that may throw exceptions    
}
catch(Exception ex) 
{
    // add error logging here
    throw;
}
414
ответ дан 22 November 2019 в 22:27
поделиться

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

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

Чтобы повторить итерацию, хотя Нет смысла перехватывать исключение в опубликованном вами примере . Не делайте этого!

2
ответ дан 22 November 2019 в 22:27
поделиться

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

Вы можете сказать Catch io. FileNotFoundExeption ex , а затем использовать альтернативный путь к файлу или что-то подобное, но все равно вызывать ошибку.

Также выполнение Throw вместо Throw Ex позволяет сохранить полная трассировка стека. Throw ex перезапускает трассировку стека из оператора throw (надеюсь, в этом есть смысл).

3
ответ дан 22 November 2019 в 22:27
поделиться

Вы не хотите бросать ex - это приведет к потере стека вызовов. См. Обработка исключений (MSDN).

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

8
ответ дан 22 November 2019 в 22:27
поделиться

Разве это не эквивалентно не обработка исключений вообще?

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

10
ответ дан 22 November 2019 в 22:27
поделиться

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

public static string SerializeDTO(DTO dto) {
  try {
      XmlSerializer xmlSer = new XmlSerializer(dto.GetType());
      StringWriter sWriter = new StringWriter();
      xmlSer.Serialize(sWriter, dto);
      return sWriter.ToString();
  }
  catch(Exception ex) {
    string message = 
      String.Format("Something went wrong serializing DTO {0}", DTO);
    throw new MyLibraryException(message, ex);
  }
}
11
ответ дан 22 November 2019 в 22:27
поделиться

Не делай этого,

try 
{
...
}
catch(Exception ex)
{
   throw ex;
}

Ты » например,

try
{
   ...
}
catch(SQLException sex)
{
   //Do Custom Logging 
   //Don't throw exception - swallow it here
}
catch(OtherException oex)
{
   //Do something else
   throw new WrappedException("Other Exception occured");
}
catch
{
   System.Diagnostics.Debug.WriteLine("Eeep! an error, not to worry, will be handled higher up the call stack");
   throw; //Chuck everything else back up the stack
}
112
ответ дан 22 November 2019 в 22:27
поделиться

C # (до C # 6) не поддерживает CIL "отфильтрованные исключения", которые поддерживает VB, поэтому в C # 1-5 одна из причин для повторной генерации исключения заключается в том, что вы не иметь достаточно информации во время catch (), чтобы определить, действительно ли вы хотите перехватить исключение.

Например, в VB вы можете сделать

Try
 ..
Catch Ex As MyException When Ex.ErrorCode = 123
 .. 
End Try

... который не будет обрабатывать MyExceptions с разными значениями ErrorCode. В C # до v6 вам нужно было бы перехватить и повторно выбросить MyException, если ErrorCode не был 123:

try 
{
   ...
}
catch(MyException ex)
{
    if (ex.ErrorCode != 123) throw;
    ...
}

Начиная с C # 6.0, вы можете фильтровать , как и в VB:

try 
{
  // Do stuff
} 
catch (Exception e) when (e.ErrorCode == 123456) // filter
{
  // Handle, other exceptions will be left alone and bubble up
}
55
ответ дан 22 November 2019 в 22:27
поделиться

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

3
ответ дан 22 November 2019 в 22:27
поделиться

Извините, но многие примеры «улучшенного дизайна» все еще ужасно пахнут или могут вводить в заблуждение. Попробовав {} catch {log; throw} просто совершенно бессмысленно. Ведение журнала исключений должно выполняться в центре приложения. исключения в любом случае всплывают в трассировке стека, почему бы не записать их где-нибудь наверху и близко к границам системы?

Следует проявлять осторожность, когда вы сериализуете свой контекст (т.е. DTO в одном данном примере) только в сообщение журнала. Он может легко содержать конфиденциальную информацию, которая, возможно, не захочет попасть в руки всех людей, имеющих доступ к файлам журнала. И если вы не добавите новую информацию в исключение, я действительно не вижу смысла в переносе исключения. У старой доброй Java есть в этом смысл, при вызове кода вызывающий должен знать, каких исключений следует ожидать. Поскольку у вас этого нет в .NET, упаковка не приносит пользы по крайней мере в 80% случаев, которые я видел.

1
ответ дан 22 November 2019 в 22:27
поделиться

В дополнение к тому, что сказали другие, см. мой ответ на связанный вопрос, который показывает, что ловля и повторное забросание не являются запретной операцией (это в VB, но часть кода может быть вызвана на C # из VB).

1
ответ дан 22 November 2019 в 22:27
поделиться

Моя основная причина наличия кода вроде:

try
{
    //Some code
}
catch (Exception e)
{
    throw;
}

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

Хотя они удобны во время отладки.

14
ответ дан 22 November 2019 в 22:27
поделиться
Другие вопросы по тегам:

Похожие вопросы: