嗨,在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;
你能建议一个更好的方法吗?
以下怎么样:
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;
这使它保持紧凑,并且只尝试释放创建的实例.确实没有必要执行嵌套,因为任何失败都会导致掉到最后并在您提供的示例中执行所有清理.
我个人尝试不在同一个方法中嵌套...除了是try/try/except/finally场景.如果我发现自己需要嵌套,那么对我来说,这是一个思考重构到另一个方法调用的好时机.
编辑由于mghie和utku的评论,有点清理了一下.
EDIT将对象创建更改为不引用应用程序,因为在此示例中不需要.
我会用这样的东西:
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;
对于接口的实现中看到这个文章,但是你可以很容易地创建自己的类似的东西.
编辑:
我刚刚注意到在链接文章中Guard()是一个过程.在我自己的代码中,我重载了返回TObject的Guard()函数,上面的示例代码假定类似的东西.当然,使用泛型可以实现更好的代码......
编辑2:
如果你想知道为什么尝试...最终在我的代码中被完全删除:在不引入内存泄漏(当析构函数引发异常)或访问冲突的可能性时,不可能删除嵌套块.因此,最好使用辅助类,并让接口的引用计数完全接管.即使某些析构函数引发异常,辅助类也可以释放它所保护的所有对象.