加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

避免嵌套的try …终于在Delphi中阻塞了

发布时间:2020-12-15 10:13:44 所属栏目:大数据 来源:网络整理
导读:我今天早上有这个想法,避免嵌套的try finally如下 procedure DoSomething;var T1,T2,T3 : TTestObject;begin T1 := TTestObject.Create('One'); try T2 := TTestObject.Create('Two'); try T3 := TTestObject.Create('Three'); try //A bunch of code; fina
我今天早上有这个想法,避免嵌套的try finally如下
procedure DoSomething;
var
  T1,T2,T3 : TTestObject;
begin
  T1 := TTestObject.Create('One');
  try
    T2 := TTestObject.Create('Two');
    try
      T3 := TTestObject.Create('Three');
      try
        //A bunch of code;
      finally
        T3.Free;
      end;
    finally
      T2.Free;
    end;
  finally
    T1.Free;
  end;
end;

通过利用接口的自动引用计数,我已经提出

Type  
  IDoFinally = interface
    procedure DoFree(O : TObject);
  end;

  TDoFinally = class(TInterfacedObject,IDoFinally)
  private
    FreeObjectList : TObjectList;
  public
    procedure DoFree(O : TObject);
    constructor Create;
    destructor Destroy; override;
  end;

//...

procedure TDoFinally.DoFree(O : TObject);
begin
  FreeObjectList.Add(O);
end;

constructor TDoFinally.Create;
begin
  FreeObjectList := TObjectList.Create(True);
end;

destructor TDoFinally.Destroy;
begin
  FreeObjectList.Free;
  inherited;
end;

所以以前的代码块变成了

procedure DoSomething;
var
  T1,T3 : TTestObject;
  DoFinally : IDoFinally;
begin
  DoFinally := TDoFinally.Create;
  T1 := TTestObject.Create('One');
  DoFinally.DoFree(T1);
  T2 := TTestObject.Create('Two');
  DoFinally.DoFree(T2);
  T3 := TTestObject.Create('Three');
  DoFinally.DoFree(T3);
  // A Bunch of code;
end;

我的问题是:这是工作还是让我忽略了一些东西?

对我来说,这看起来很酷,并且通过减少嵌套数量,使代码更容易阅读。它也可以扩展为存储匿名方法的列表来运行,以执行诸如关闭文件,查询等的操作…

解决方法

是的,它有效。

也许唯一不同的是,原始代码的嵌套的try-finally块和使用引用计数对象来管理其他对象的生命周期的技术是如果有一个问题销毁任何对象会发生什么。如果任何对象被破坏时有异常,嵌套的try-finally块将确保任何剩余的对象仍然可以被释放。 TDoFinally中的TObjectList不这样做;如果列表中的任何项目不能被销毁,列表中的任何后续项目将被泄漏。

实际上,这不是一个真正的问题。没有析构函数应该抛出异常。如果是这样,没有任何方法可以从中恢复,所以没有任何事情会因为它而泄漏。您的程序应该暂时终止,因此整洁的清理程序并不重要。

顺便提一句,JCL已经提供了用于管理本地对象的生命周期的ISafeGuard和IMultiSafeGuard接口。例如,您可以重写代码,如下所示:

uses JclSysUtils;

procedure DoSomething;
var
  T1,T3: TTestObject;
  G: IMultiSafeGuard;
begin
  T1 := TTestObject(Guard(TTestObject.Create('One'),G));
  T2 := TTestObject(Guard(TTestObject.Create('Two'),G));
  T3 := TTestObject(Guard(TTestObject.Create('Three'),G));
  // A Bunch of code;
end;

该库也不解决析构函数中的异常。

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读