当前位置:  开发笔记 > 编程语言 > 正文

做嵌套TRY/FINALLY语句的最佳实践

如何解决《做嵌套TRY/FINALLY语句的最佳实践》经验,为你挑选了2个好方法。

嗨,在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;

你能建议一个更好的方法吗?



1> skamradt..:

以下怎么样:

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将对象创建更改为不引用应用程序,因为在此示例中不需要.


我使用自己的InitialiseNil例程处理这个问题,该例程采用多个参数,FreeAndNil例程也采用多个参数.它使上面的代码读得更好一些.
1.如果构造函数中存在异常,则必须始终将create放在try/finally-free之前 - 初始化为nil以防止这是一个丑陋的黑客.2.你要么通过一个非零所有者来创建或自己释放对象 - 永远不要两个!

2> mghie..:

我会用这样的东西:

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:

如果你想知道为什么尝试...最终在我的代码中被完全删除:在不引入内存泄漏(当析构函数引发异常)或访问冲突的可能性时,不可能删除嵌套块.因此,最好使用辅助类,并让接口的引用计数完全接管.即使某些析构函数引发异常,辅助类也可以释放它所保护的所有对象.

推荐阅读
依然-狠幸福
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有