你应该如何安全地创建和释放多个对象?
基本上,这种事情:
  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 次  |  
        
|   最近记录:  |