ПриМеЧание
Можно.создать.событие.FirstChanceException.класса.AppDomain.и.получать.инфор-
мацию.об.исключениях.еще.до.того,.как.CLR.начнет.искать.их.обработчики .Подробно.
эта.тема.рассматривается.в.главе.22
Блок finally
Код блока
finally
выполняется всегда
1
. Обычно этот код производит очистку по-
сле выполнения блока
try
. Если в блоке
try
был открыт некий файл, блок
finally
должен содержать закрывающий этот файл код:
private void ReadData(String pathname) {
FileStream fs = null;
try {
fs = new FileStream(pathname, FileMode.Open);
// Обработка данных в файле
}
catch (IOException) {
// Код восстановления после исключения IOException
}
finally {
// Файл обязательно следует закрыть
if (fs != null) fs.Close();
}
}
1
Прерывание потока или выгрузка домена приложений является источником исключения
ThreadAbortException, обеспечивающего выполнение блока finally. Если же поток преры-
вается функцией TerminateThread или методом FailFast класса System.Environment, блок
finally не выполняется. Разумеется, Windows производит очистку всех ресурсов, которые
использовались прерванным процессом.
502
Глава.20 .Исключения.и.управление.состоянием
Если код блока
try
выполняется без исключений, файл закрывается. Впрочем,
поскольку даже исключение не помешает выполнению кода в блоке
finally
, файл
гарантированно будет закрыт. А если поместить инструкцию закрытия файла после
блока
finally
, в случае неперехваченного исключения файл останется открытым
(до следующего прохода уборщика мусора).
Блок
try
может существовать и без блока
finally
, ведь иногда его код просто
не требует последующей очистки. Однако если вы решили создать блок
finally
,
его следует поместить после всех блоков
catch
. И помните, что одному
try
может
соответствовать только один блок
finally
.
Достигнув конца блока
finally
, поток переходит к инструкции, расположенной
после этого блока. Запомните, что в блок
finally
помещается код для выполнения
завершающей очитски. И он должен выполнять только те действия, которые не-
обходимы для отмены операций, начатых в блоке
try
. Код блоков
catch
и
finally
следует делать по возможности коротким (ограничиваясь одной или двумя стро-
ками) и по возможности работающим без исключений. Однако иногда случается
так, что источником исключения становится код восстановления или код очистки.
Обычно это указывает на наличие серьезных ошибок.
Всегда существует вероятность того, что во время выполенния кода восстанов-
ления или очистки произойдет сбой, и будет выдано исключение. Впрочем, такая
ситуация маловероятна, а ее возникновение свидетельствует о возникновении очень
серьезных проблем в программе (скорее всего, о повреждении текущего состояния).
Если источником исключения становятся блоки
catch
или
finally
, CLR продол-
жает работу как в случае, когда исключение генерируется после блока
finally
.
Просто при этом теряется информация о первом исключении, вброшенном в блоке
try
. Скорее всего (и даже желательно), это новое исключение останется необрабо-
танным. После этого CLR завершает процесс, уничтожая поврежденное состояние.
Продолжение работы приложения в подобном случае привело бы к непредсказуе-
мым результатам и, вероятно, к появлению дефектов в системе безопасности.
С моей точки зрения, для механизма обработки исключений следовало бы вы-
брать другие ключевые слова. Ведь программисту нужно всего лишь выполнить
фрагмент кода. А если что-то пойдет не так, либо восстановить приложение после
ошибки и двигаться дальше, либо вернуться в состояние до возникновения про-
блем и сообщить о неполадках. Программистам также нужно гарантированное
выполнение завершающей очистки. Слева показан код, правильный с точки зрения
компилятора, а справа — синтаксис, который предпочел бы видеть я:
void Method() {
try {
...
}
void Method() {
try {
...
}
503
Механика.обработки.исключений
catch (XxxException) {
...
}
catch (YyyException) {
...
}
catch {
...; throw;
}
finally {
...
}
}
handle (XxxException) {
...
}
handle (YyyException) {
...
}
compensate {
...; throw;
}
cleanup {
...
}
}
Do'stlaringiz bilan baham: |