Со сборкой мусора неправильно сравнивать, т. к. ресурс освобождается детерминированно, это просто автоматизация закрытия ресурса при выходе из скоупа. В Java эквивалентом является только лишь try-with-resources.
MylnikovDm писал(а):Лично меня использование try-finnaly-end не напрягает.
Сейчас напряжёт, смотри:
Код: Выделить всё
procedure CopySrcToTwoDsts;
var
src, dst0, dst1: TStream;
srcStart: int64;
begin
src := OpenSrcStream;
try
srcStart := src.Position;
dst0 := OpenDst0Stream;
try
dst1 := OpenDst1Stream;
try
dst0.CopyFrom(src, 0);
src.Position := srcStart;
dst1.CopyFrom(src, 0);
finally
FreeAndNil(dst1);
end;
finally
FreeAndNil(dst0);
end;
finally
FreeAndNil(src);
end;
end;
Вариант без лесенки (который обычно в Паскале и используют, чтобы уменьшить вложенность):
Код: Выделить всё
procedure CopySrcToTwoDsts;
var
src, dst0, dst1: TStream;
srcStart: int64;
begin
src := nil;
dst0 := nil;
dst1 := nil;
try
src := OpenSrcStream;
srcStart := src.Position;
dst0 := OpenDst0Stream;
dst1 := OpenDst1Stream;
dst0.CopyFrom(src, 0);
src.Position := srcStart;
dst1.CopyFrom(src, 0);
finally
FreeAndNil(dst1);
FreeAndNil(dst0);
FreeAndNil(src);
end;
end;
А вот как это выглядит с RAII:
Код: Выделить всё
// type IAutoClosingStream = ...
procedure CopySrcToTwoDsts;
var
src, dst0, dst1: IAutoClosingStream;
srcStart: int64;
begin
src := OpenSrcStream;
srcStart := src.Position;
dst0 := OpenDst0Stream;
dst1 := OpenDst1Stream;
dst0.CopyFrom(src);
src.Position := srcStart;
dst1.CopyFrom(src);
end;
Ну в каком месте первые два читаемей или устойчивей к ошибкам? Наоборот, они содержат бойлерплейт, который не несёт семантической информации, поэтому ты привыкаешь пропускать его глазами. Ошибки могут возникать и не сразу, а по мере внесения изменений в код — например, банально можно добавить четвёртый объект и забыть добавить его во все нужные места (блок зануления и блок finally), и какое-то время это по случайности будет работать.
А вот ещё вариант. Ты захватываешь критическую секцию и не используешь
try-finally, ведь под ней простые присваивания:
Код: Выделить всё
EnterCriticalSection(cs);
newHead^.next := head;
head := newHead;
inc(nItems);
LeaveCriticalSection(cs);
А потом в неё добавляется дополнительная операция:
Код: Выделить всё
EnterCriticalSection(cs);
if nItems >= 1000 then raise Exception.Create('Слишком много элементов в списке.');
newHead^.next := head;
head := newHead;
inc(nItems);
LeaveCriticalSection(cs);
Ой, окружающий код внезапно стал неправильным, вот незадача.