Gle*_*003 19
使用接口而不是对象.它们被引用计数并在引用计数达到0时自动释放.
Cod*_*ats 13
我编写了一个函数GC(obj:TObject)(用于Garbage Collect),它接受一个对象并在执行离开当前方法时释放它.它有点像Try Finally Free块的单行速记功能.
代替:
procedure Test;
var AQuery: TQuery;
begin
AQuery := TQuery.Create(nil);
try
...
finally
FreeAndNil(AQuery);
end;
end;
Run Code Online (Sandbox Code Playgroud)
我只有:
procedure Test;
var AQuery: TQuery;
begin
AQuery := TQuery.Create(nil);
GC(AQuery);
...
end;
Run Code Online (Sandbox Code Playgroud)
GC函数只是以接口的形式返回一个对象.
function GC(obj: TObject): IGarbo;
begin
Result := TGarbo.Create(obj);
end;
Run Code Online (Sandbox Code Playgroud)
因为TGarbo类来自TInterfacedObject,所以当TGarbo对象超出范围时,它将自动被释放.在TGarbo对象的析构函数中,它还释放了在它的构造函数(您在GC函数中传递的对象)中传递给它的对象.
type
IGarbo = interface
['{A6E17957-C233-4433-BCBD-3B53C0C2C596}']
function Obj: TObject;
end;
TGarbo = class(TInterfacedObject, IGarbo)
private
FObj: TObject;
public
constructor Create(AObjectToGC: TObject);
destructor Destroy; override;
function Obj: TObject;
end;
{ TGarbo }
constructor TGarbo.Create(AObjectToGC: TObject);
begin
inherited Create;
FObj := AObjectToGC;
end;
destructor TGarbo.Destroy;
begin
if Assigned(FObj) then
FreeAndNil(FObj);
inherited;
end;
function TGarbo.Obj: TObject;
begin
Result := FObj;
end;
Run Code Online (Sandbox Code Playgroud)
被困在Delphi 7的世界里,在不久的将来没有升级到带有内置垃圾收集的Delphi版本,我沉迷于使用这种简单的方法来轻松释放本地临时对象!:)
沿着接口,您可以Guard在JclSysUtils单元中尝试该功能,这是免费的Jedi代码库的一部分.它允许您将对象与单独的接口引用相关联,因此当该接口引用被销毁时,该对象将随之被销毁.当您无法修改正在使用的类以使其支持自己的接口时,这可能很有用.
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
Run Code Online (Sandbox Code Playgroud)
对象和GetMem分配指针有重载.还有IMultiSafeGuard,可以确保释放多个对象.
如果您有工厂函数,则可能正在创建对象,设置其某些属性,然后返回它.如果在设置属性时发生异常,您将需要确保释放该对象,因为您无法返回该对象.一种方法是这样的:
function Slurp(const source: TFileName): TStrings;
begin
Result := TStringList.Create;
try
Result.LoadFromFile(source);
except
Result.Free;
raise;
end;
end;
Run Code Online (Sandbox Code Playgroud)
随着Guard,它会变成这样:
function Slurp(const source: TFileName): TStrings;
var
G: ISafeGuard;
begin
Result := Guard(TStringList.Create, G) as TStrings;
Result.LoadFromFile(source);
G.ReleaseItem;
end;
Run Code Online (Sandbox Code Playgroud)
该ReleaseItem方法撤销ISafeGuard对象的所有权.如果在发生异常之前发生异常,则当堆栈展开并释放接口时,防护将释放该对象.
我不得不说,我不喜欢"隐藏"一个物体的自由.拥有传统代码要好得多:
MyObject := TObject.Create;
try
// do stuff
finally
FreeAndNil(MyObject);
end;
Run Code Online (Sandbox Code Playgroud)
它不会出错,按预期工作,人们认识到这种模式.