你应该如何安全地创建和释放多个对象?
基本上,这种事情:
newOrderSource := TWebNewOrderSource.Create();
twData := TTWData.Create();
webData := TWebData.Create();
try
//do stuff
finally
newOrderSource.Free();
twData.Free();
webData.Free();
end;
Run Code Online (Sandbox Code Playgroud)
在这种情况下,第二个和第三个create命令不安全,因为它们与数据库一起使用.我是否应该将所有Creates放入try块并检查它们是否在我免费呼叫之前被分配了?
chu*_*ckj 15
如果首先将nil指定给变量,可以使用一个try块执行此操作,例如,
newOrderSource := nil;
twData := nil;
webData := nil;
try
newOrderSource := TWebNewOrderSource.Create();
twData := TTWData.Create();
webData := TWebData.Create();
//do stuff
finally
webData.Free();
twData.Free();
newOrderSource.Free();
end;
Run Code Online (Sandbox Code Playgroud)
这工作,因为Free()检查Self的nil.
Dav*_*nan 10
我确信每个人都知道,管理对象的标准方法是这样的:
A := TMyObject.Create;
try
A.DoSomething;
finally
A.Free;
end;
Run Code Online (Sandbox Code Playgroud)
如果在TMyObject.Create那时存在异常,则将调用析构函数,然后引发异常.在那种情况下A不会被分配.
当您有多个对象时,可以重复该模式:
A := TMyObject.Create;
try
B := TMyObject.Create;
try
A.DoSomething;
B.DoSomething;
finally
B.Free;
end;
finally
A.Free;
end;
Run Code Online (Sandbox Code Playgroud)
这很快变得一团糟,因此问题.
标准技巧是利用Free可以在nil对象引用上安全地调用的事实.
A := nil;
B := nil;
try
A := TMyObject.Create;
B := TMyObject.Create;
A.DoSomething;
B.DoSomething;
finally
B.Free;
A.Free;
end;
Run Code Online (Sandbox Code Playgroud)
这确实有一个小的弱点,即它不能适应异常,B.Free但将此视为可以忽略的失败条件并非没有道理.析构函数不应该引发异常.如果他们这样做,那么你的系统可能会被无法破坏.
随着更多对象的添加,上面的这种模式会变得有点混乱,所以我个人使用以下帮助方法.
procedure InitialiseNil(var Obj1); overload;
procedure InitialiseNil(var Obj1, Obj2); overload;
procedure InitialiseNil(var Obj1, Obj2, Obj3); overload;
procedure FreeAndNil(var Obj1); overload;
procedure FreeAndNil(var Obj1, Obj2); overload;
procedure FreeAndNil(var Obj1, Obj2, Obj3); overload;
Run Code Online (Sandbox Code Playgroud)
事实上,我的代码具有更多参数的版本.为了便于维护,此代码全部由简短的Python脚本自动生成.
这些方法以明显的方式实现,例如
procedure FreeAndNil(var Obj1, Obj2);
var
Temp1, Temp2: TObject;
begin
Temp1 := TObject(Obj1);
Temp2 := TObject(Obj2);
Pointer(Obj1) := nil;
Pointer(Obj2) := nil;
Temp1.Free;
Temp2.Free;
end;
Run Code Online (Sandbox Code Playgroud)
这允许我们像这样重写上面的示例:
InitialiseNil(A, B);
try
A := TMyObject.Create;
B := TMyObject.Create;
A.DoSomething;
B.DoSomething;
finally
FreeAndNil(B, A);
end;
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3052 次 |
| 最近记录: |