, если у вас установлен APEX, функция APEX_UTIL.string_to_table
делает именно это.
Первый; то, как это делает код в статье, - зло. throw ex
сбросит стек вызовов в исключении до точки, в которой находится этот оператор throw; потеря информации о том, где на самом деле было создано исключение.
Во-вторых, если вы просто поймаете и повторно выбросите вот так, я не вижу никакой дополнительной ценности, приведенный выше пример кода будет таким же хорошим (или, учитывая throw ex
bit, даже лучше) без try-catch.
Однако бывают случаи, когда вы можете захотеть перехватить и повторно вызвать исключение. Ведение журнала может быть одним из них:
try
{
// code that may throw exceptions
}
catch(Exception ex)
{
// add error logging here
throw;
}
В примере кода, который вы разместили, на самом деле нет смысла перехватывать исключение, так как ничего не делается с уловом, он просто повторно отображается, на самом деле он больше вреда, чем пользы, поскольку стек вызовов теряется.
Однако вы могли бы перехватить исключение, чтобы выполнить некоторую логику (например, закрыть соединение sql или блокировку файла, или просто вести журнал), в случае исключения выбросить его обратно в вызывающий код для обработки. Это было бы более распространено на бизнес-уровне, чем в коде внешнего интерфейса, поскольку вы можете захотеть, чтобы кодировщик, реализующий ваш бизнес-уровень, обрабатывал исключение.
Чтобы повторить итерацию, хотя Нет смысла перехватывать исключение в опубликованном вами примере . Не делайте этого!
Это зависит от того, что вы делаете в блоке catch, и хотите ли вы передать ошибку в вызывающий код или нет.
Вы можете сказать Catch io. FileNotFoundExeption ex
, а затем использовать альтернативный путь к файлу или что-то подобное, но все равно вызывать ошибку.
Также выполнение Throw
вместо Throw Ex
позволяет сохранить полная трассировка стека. Throw ex перезапускает трассировку стека из оператора throw (надеюсь, в этом есть смысл).
Вы не хотите бросать ex - это приведет к потере стека вызовов. См. Обработка исключений (MSDN).
И да, try ... catch не делает ничего полезного (кроме потери стека вызовов - так что на самом деле это еще хуже - если только по какой-то причине вы этого не сделали хочу раскрыть эту информацию).
Разве это не эквивалентно не обработка исключений вообще?
Не совсем, это не то же самое. Он сбрасывает трассировку стека исключения. Хотя я согласен, что это, вероятно, ошибка и, следовательно, пример неправильного кода.
Достоверной причиной повторного создания исключений может быть то, что вы хотите добавить информацию к исключению или, возможно, обернуть исходное исключение в одно из ваших собственных :
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);
}
}
Не делай этого,
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
}
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
}
Одной из возможных причин перехвата является отключение любых фильтров исключений на более глубоких уровнях стека от фильтрации вниз ( случайная старая ссылка ). Но, конечно, если бы это было намерением, там был бы комментарий, говорящий об этом.
Извините, но многие примеры «улучшенного дизайна» все еще ужасно пахнут или могут вводить в заблуждение. Попробовав {} catch {log; throw} просто совершенно бессмысленно. Ведение журнала исключений должно выполняться в центре приложения. исключения в любом случае всплывают в трассировке стека, почему бы не записать их где-нибудь наверху и близко к границам системы?
Следует проявлять осторожность, когда вы сериализуете свой контекст (т.е. DTO в одном данном примере) только в сообщение журнала. Он может легко содержать конфиденциальную информацию, которая, возможно, не захочет попасть в руки всех людей, имеющих доступ к файлам журнала. И если вы не добавите новую информацию в исключение, я действительно не вижу смысла в переносе исключения. У старой доброй Java есть в этом смысл, при вызове кода вызывающий должен знать, каких исключений следует ожидать. Поскольку у вас этого нет в .NET, упаковка не приносит пользы по крайней мере в 80% случаев, которые я видел.
В дополнение к тому, что сказали другие, см. мой ответ на связанный вопрос, который показывает, что ловля и повторное забросание не являются запретной операцией (это в VB, но часть кода может быть вызвана на C # из VB).
Моя основная причина наличия кода вроде:
try
{
//Some code
}
catch (Exception e)
{
throw;
}
заключается в том, что я могу иметь точку останова в перехвате, у которого есть экземпляр объекта исключения. Я часто этим занимаюсь во время разработки / отладки. Конечно, компилятор выдает предупреждение обо всех неиспользуемых e, и в идеале их следует удалить перед сборкой релиза.
Хотя они удобны во время отладки.