嗨,在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;你能推荐一种更好的方法吗?
发布于 2008-12-29 17:25:21
下面的内容如何:
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;这使其保持紧凑,并且仅尝试释放已创建的实例。真的不需要执行嵌套,因为任何失败都会导致丢弃到finally并执行您提供的示例中的所有清理。
就我个人而言,我尽量不在相同的方法中嵌套...例外是try/try/except/finally方案。如果我发现自己需要嵌套,那么对我来说,这是考虑将重构转换为另一个方法调用的绝佳时机。
EDIT将对象创建更改为不引用应用程序,因为在本例中这不是必需的。
发布于 2008-12-29 17:38:48
我会使用类似这样的东西:
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;有关该接口的实现,请参阅this文章,但您可以很容易地自己创建类似的东西。
编辑:
我刚刚注意到在链接的文章中,Guard()是一个过程。在我自己的代码中,我重载了返回TObject的Guard()函数,上面的示例代码假设了类似的情况。当然,有了泛型,现在可以编写更好的代码。
EDIT 2:
如果你想知道为什么尝试..。最后在我的代码中被完全删除:如果不引入内存泄漏(当析构函数引发异常)或访问冲突的可能性,就不可能删除嵌套的块。因此,最好使用助手类,让接口的引用计数完全接管。helper类可以释放它保护的所有对象,即使一些析构函数引发异常也是如此。
发布于 2008-12-30 09:29:59
还有另一种没有嵌套try的代码变体...我终于想到了这一点。如果您没有在构造函数的AOwner参数设置为nil的情况下创建组件,那么您可以简单地使用VCL免费提供的生命周期管理:
var
cds1: TClientDataSet;
cds2: TClientDataSet;
cds3: TClientDataSet;
cds4: TClientDataSet;
begin
cds1 := TClientDataSet.Create(nil);
try
// let cds1 own the other components so they need not be freed manually
cds2 := TClientDataSet.Create(cds1);
cds3 := TClientDataSet.Create(cds1);
cds4 := TClientDataSet.Create(cds1);
///////////////////////////////////////////////////////////////////////
/// DO WHAT NEEDS TO BE DONE
///////////////////////////////////////////////////////////////////////
finally
cds1.Free;
end;
end;我非常相信小代码(如果它不是太模糊的话)。
https://stackoverflow.com/questions/398137
复制相似问题