Cha*_*iga 20 delphi memory-management object-lifetime try-finally
嗨,在delphi中执行嵌套try和finally语句的最佳方法是什么?
var cds1 : TClientDataSet;
cds2 : TClientDataSet;
cds3 : TClientDataSet;
cds4 : TClientDataSet;
begin
cds1 := TClientDataSet.Create(application );
try
cds2 := TClientDataSet.Create(application );
try
cds3 := TClientDataSet.Create(application );
try
cds4 := TClientDataSet.Create(application );
try
///////////////////////////////////////////////////////////////////////
/// DO WHAT NEEDS TO BE DONE
///////////////////////////////////////////////////////////////////////
finally
cds4.free;
end;
finally
cds3.free;
end;
finally
cds2.free;
end;
finally
cds1.free;
end;
end;
Run Code Online (Sandbox Code Playgroud)
你能建议一个更好的方法吗?
ska*_*adt 30
以下怎么样:
var cds1 : TClientDataSet;
cds2 : TClientDataSet;
cds3 : TClientDataSet;
cds4 : TClientDataSet;
begin
cds1 := Nil;
cds2 := Nil;
cds3 := Nil;
cds4 := Nil;
try
cds1 := TClientDataSet.Create(nil);
cds2 := TClientDataSet.Create(nil);
cds3 := TClientDataSet.Create(nil);
cds4 := TClientDataSet.Create(nil);
///////////////////////////////////////////////////////////////////////
/// DO WHAT NEEDS TO BE DONE
///////////////////////////////////////////////////////////////////////
finally
freeandnil(cds4);
freeandnil(cds3);
freeandnil(cds2);
freeandnil(Cds1);
end;
end;
Run Code Online (Sandbox Code Playgroud)
这使它保持紧凑,并且只尝试释放创建的实例.确实没有必要执行嵌套,因为任何失败都会导致掉到最后并在您提供的示例中执行所有清理.
我个人尝试不在同一个方法中嵌套...除了是try/try/except/finally场景.如果我发现自己需要嵌套,那么对我来说,这是一个思考重构到另一个方法调用的好时机.
EDIT将对象创建更改为不引用应用程序,因为在此示例中不需要.
mgh*_*hie 18
我会用这样的东西:
var
Safe: IObjectSafe;
cds1 : TClientDataSet;
cds2 : TClientDataSet;
cds3 : TClientDataSet;
cds4 : TClientDataSet;
begin
Safe := ObjectSafe;
cds1 := Safe.Guard(TClientDataSet.Create(nil)) as TClientDataSet;
cds2 := Safe.Guard(TClientDataSet.Create(nil)) as TClientDataSet;
cds3 := Safe.Guard(TClientDataSet.Create(nil)) as TClientDataSet;
cds4 := Safe.Guard(TClientDataSet.Create(nil)) as TClientDataSet;
///////////////////////////////////////////////////////////////////////
/// DO WHAT NEEDS TO BE DONE
///////////////////////////////////////////////////////////////////////
// if Safe goes out of scope it will be freed and in turn free all guarded objects
end;
Run Code Online (Sandbox Code Playgroud)
对于接口的实现中看到这个文章,但是你可以很容易地创建自己的类似的东西.
编辑:
我刚刚注意到在链接文章中Guard()是一个过程.在我自己的代码中,我重载了返回TObject的Guard()函数,上面的示例代码假定类似的东西.当然,使用泛型可以实现更好的代码......
编辑2:
如果你想知道为什么尝试...最终在我的代码中被完全删除:在不引入内存泄漏(当析构函数引发异常)或访问冲突的可能性时,不可能删除嵌套块.因此,最好使用辅助类,并让接口的引用计数完全接管.即使某些析构函数引发异常,辅助类也可以释放它所保护的所有对象.