首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >执行嵌套TRY / FINALLY语句的最佳实践

执行嵌套TRY / FINALLY语句的最佳实践
EN

Stack Overflow用户
提问于 2008-12-29 17:16:37
回答 6查看 5.8K关注 0票数 20

嗨,在delphi中做嵌套try & finally语句的最好方法是什么?

代码语言:javascript
复制
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;

你能推荐一种更好的方法吗?

EN

回答 6

Stack Overflow用户

回答已采纳

发布于 2008-12-29 17:25:21

下面的内容如何:

代码语言:javascript
复制
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方案。如果我发现自己需要嵌套,那么对我来说,这是考虑将重构转换为另一个方法调用的绝佳时机。

多亏了mghieutku的评论,EDIT清理了一下。

EDIT将对象创建更改为不引用应用程序,因为在本例中这不是必需的。

票数 31
EN

Stack Overflow用户

发布于 2008-12-29 17:38:48

我会使用类似这样的东西:

代码语言:javascript
复制
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类可以释放它保护的所有对象,即使一些析构函数引发异常也是如此。

票数 18
EN

Stack Overflow用户

发布于 2008-12-30 09:29:59

还有另一种没有嵌套try的代码变体...我终于想到了这一点。如果您没有在构造函数的AOwner参数设置为nil的情况下创建组件,那么您可以简单地使用VCL免费提供的生命周期管理:

代码语言:javascript
复制
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;

我非常相信小代码(如果它不是太模糊的话)。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/398137

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档