Вдоль линий интерфейсов, вы можете попробовать функцию Guard
в блоке JclSysUtils
, часть бесплатной библиотеки кодов джедаев . Он позволяет связать объект с отдельной интерфейсной ссылкой, поэтому, когда эта интерфейсная ссылка уничтожается, объект уничтожается вместе с ним. Это может быть полезно, когда у вас нет возможности изменить используемые вами классы, чтобы они поддерживали собственные интерфейсы.
var
G: ISafeGuard;
foo: TStrings;
begin
// Guard returns TObject, so a type-cast is necessary
foo := Guard(TStringList.Create, G) as TStrings;
// Use the object as normal
foo.Add('bar');
end; // foo gets freed automatically as G goes out of scope
Существуют перегрузки для объектов и GetMem
-распределенных указателей. Существует также IMultiSafeGuard
, который может обеспечить освобождение нескольких объектов.
Если у вас есть фабричная функция, возможно, вы создаете объект, устанавливаете некоторые его свойства и затем возвращаете его. Если при настройке свойств возникает исключение, вам нужно убедиться, что вы освободили объект, поскольку не можете его вернуть. Один из способов сделать это так:
function Slurp(const source: TFileName): TStrings;
begin
Result := TStringList.Create;
try
Result.LoadFromFile(source);
except
Result.Free;
raise;
end;
end;
С Guard
это станет так:
function Slurp(const source: TFileName): TStrings;
var
G: ISafeGuard;
begin
Result := Guard(TStringList.Create, G) as TStrings;
Result.LoadFromFile(source);
G.ReleaseItem;
end;
Метод ReleaseItem
отменяет владение ISafeGuard
объектом. Если перед тем, как это произойдет, возникнет исключение, то, когда стек раскручивается и интерфейс освобождается, охранник освобождает объект.