Delphi应用程序中存在哪些自动释放对象的技术?
使用接口而不是对象。它们是引用计数的,当引用计数达到0时会自动释放。
我编写了一个名为GC(垃圾回收)的函数,它接受一个对象并在执行退出当前方法时释放它。这有点像一个一行代码的缩写函数,用于一个Try Finally Free块。
与其写成:
procedure Test;
var AQuery: TQuery;
begin
AQuery := TQuery.Create(nil);
try
...
finally
FreeAndNil(AQuery);
end;
end;
我只是拥有:
procedure Test;
var AQuery: TQuery;
begin
AQuery := TQuery.Create(nil);
GC(AQuery);
...
end;
GC函数只是以接口的形式返回一个对象。
function GC(obj: TObject): IGarbo;
begin
Result := TGarbo.Create(obj);
end;
由于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;
由于困在Delphi 7的世界里,看不到在不久的将来升级到内置垃圾回收版本的希望,因此我沉迷于使用这种简便的方法轻松释放本地临时对象! :)
在接口方面,您可以尝试使用免费的Jedi Code Library中的JclSysUtils
单元中的Guard
函数。它允许您将对象与一个独立的接口引用相关联,因此当该接口引用被销毁时,该对象也会被销毁。当您无法修改正在使用的类以使其支持自己的接口时,这可能非常有用。
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;
< p > ReleaseItem
方法撤销 ISafeGuard
对该对象的所有权。如果在此之前发生异常,则随着堆栈展开和接口释放,守护程序将释放该对象。
我必须说,我不喜欢“隐藏”对象的自由。传统代码更好:
MyObject := TObject.Create;
try
// do stuff
finally
FreeAndNil(MyObject);
end;
智能指针在使用Delphi 2009时非常有效。
如果您使用Delphi for .Net / Delphi Prism,您将获得垃圾回收功能,它会处理所有内存释放。