Различия между вашим примером и аналогичным кодом, в котором есть только один внешний, catch:
1) Если внутренний блок выдает сообщение, то перед вызовом Close()
печатается сообщение.Это может быть важно, если Close()
также содержит ведение журнала.
2) Если внутреннее исключение выбрасывается и перехватывается, а затем в блоке finally Close()
также выбрасывает, вы получаете дваисключения, и вы обрабатываете два исключения.Только с одним блоком catch, если Close()
throws, то что произойдет дальше, может зависеть от языка, но вы не получите два сообщения об ошибке.Я ожидаю, что второе исключение заменит первое, но я не клянусь, что это происходит на всех языках с finally
или даже на всех языках, которые я использовал ...
3) //Show error message
это просто комментарий, он ничего не делает.Автор может иметь намерение показать сообщение об ошибке различное в двух разных случаях.Внутренний сказал бы: «Сбой чтения», а внешний сказал бы: «Не удается открыть файл».Или что-то типа того.Чтобы добиться этого только с одним блоком перехвата, вы можете установить и проверить флаг, указывающий на прогресс (что, вероятно, не делает код проще, чем два блока перехвата), или вы можете полагаться на само исключение, которое будет содержать соответствующее сообщение об ошибке (в этом случае удачи в интеграции вашей платформы локализации с функциями генерирования исключений во встроенные или сторонние библиотеки).
Обратите внимание, что даже если у вас есть только один улов, вам все равно нужно две попытки из-за finally
.Это нехорошо:
try {
TextReader tr = new StreamReader("filename");
string content = tr.ReadToEnd();
} catch(Exception ex) {
// show error message
} finally {
tr.Close();
}
Поскольку, по внешнему виду этого языка, tr
не будет находиться в области видимости в блоке finally
, поэтому мы не можем закрыть его там.Мы должны закрыть его внутри блока, который занимается его созданием.Возможно, мы могли бы справиться с этим следующим образом:
TextReader tr = null;
try {
tr = new StreamReader("filename");
string content = tr.ReadToEnd();
} catch(Exception ex) {
// show error message
} finally {
if (tr != null) {
tr.Close();
}
}
Но это не сильно упрощает ситуацию по сравнению с исходным кодом, у нас все еще есть различия 2-3, с которыми приходится бороться, и теперь мыне обрабатывать исключения из Close()
вообще.Так что для многих целей оригинальный код с несколькими try / catch был лучше.