Delphi - Какой "правильный" порядок для блоков исключений и окончательно?
Предположим, у меня есть следующая процедура:
function ReadFile(f : TFilename) : Boolean;
var
fs : TFileStream;
begin
Result := False;
try
fs := TFileStream.Create(f, ...);
try
// read file ...
Result := True;
finally
FreeAndNil(fs);
end;
except
// handle exceptions ...
end;
end;
Каковы последствия наличия except
а также finally
транспонированная? Я видел множество постов с ними обоими способами, но я не видел четкого объяснения того, что уместно в каких случаях (я все еще думаю, что любопытно, что в вышеупомянутой конструкции, finally
блок выполняется после except
блок!).
Я также видел посты, которые предполагают, что смешивание try..except
а также try..finally
блоки не очень хорошая идея. Как вы можете избежать этого в ситуациях, когда процедура вызывает исключение как часть нормальной работы, например, в некоторых процедурах Indy?
1 ответ
Нет единственно правильного способа написать это. Два варианта делают разные вещи. Вы можете предпочесть одну версию в одном сценарии, а другую - в другом.
Версия 1, наконец, самая внутренняя
function ReadFile(f : TFilename) : Boolean;
var
fs : TFileStream;
begin
Result := False;
try
fs := TFileStream.Create(f, ...);
try
// read file ...
Result := True;
finally
FreeAndNil(fs);
end;
except
// handle exceptions ...
end;
end;
Версия 2, наконец, самая внешняя
function ReadFile(f : TFilename) : Boolean;
var
fs : TFileStream;
begin
Result := False;
fs := TFileStream.Create(f, ...);
try
try
// read file ...
Result := True;
except
// handle exceptions ...
end;
finally
FreeAndNil(fs);
end;
end;
Большая разница в том, как код ведет себя, если TFileStream.Create
Возникает исключение, далеко не правдоподобное событие. В версии 1 исключение будет поймано и обработано внутри ReadFile
, В версии 2 исключение будет передано из ReadFile
и вверх по цепочке обработчиков исключений.
Asides
Вы заявляете:
Я все еще думаю, что любопытно, что в приведенной выше конструкции блок finally выполняется после блока исключений!
Это не относится к коду в вашем вопросе, версия 1 выше. Возможно, вы еще не до конца понимаете, как в конечном итоге работают блоки.
Распространенная ошибка, которая часто наблюдается, - это желание отлавливать и обрабатывать исключения как можно скорее. Это неправильная стратегия. Весь смысл исключения состоит в том, что оно не должно происходить, и вы обычно не знаете, что делать, когда это произойдет. Ваша цель - обрабатывать исключения как можно позже. Для подавляющего большинства кода вы просто не должны обрабатывать исключения. Пусть они всплывают вверх в той точке кода, которая способна справиться с ошибкой.