我最近绊倒造成一些很老的代码,我写了明显假设在with语句中使用该接口引用的问题将尽快with块被释放左键 - 有点像一个隐含的try-finally块(类似的C#using语句如果我理解正确的)。

显然(在2009年的Delphi)这不是(不再?)的情况。有谁知道什么时候会发生?或者是我的代码只是简单的错误,开始用?

要阐明,这里是一个简化的例子:

type
  IMyIntf = interface;
  TSomeObject = class(TInterfacedObject, IMyIntf)
  protected
    constructor Create; override; // creates some sort of context
    destructor Destroy; override; // cleans up the context created in Create
  public
    class function GetMyIntf: IMyIntf; //a factory method, calling the constructor
  end;

procedure TestIt;
begin
  DoSomething;
  with (TSomeObject.GetMyIntf) do
    begin
      DoStuff;
      DoMoreStuff;
    end; // <- expected: TSomeObject gets destroyed because its ref.count is decreased to 0
  DoSomethingElse;
end; // <- this is where TSomeObject.Destroy actually gets called

每当有人开始老“with是邪恶的”的说法,这是始终是一个例子,我脑子里想这让我继续走下去“是的,但是......”。好像我错了...任何人都可以证实?

有帮助吗?

解决方案

在帕斯卡保留字的with / Delphi的仅用于容易访问的记录或对象/类成员(即为了不提记录的/对象的/类的名称)。这是从涉及到垃圾回收的C#with很大的不同。它在Pascal语言已经存在的那一天开始records出生,简化代码调用许多数据成员(当时简称“田”)。

要总结,with无关与垃圾收集,内存或对象实例的破坏释放。那些在with头部构造的对象可能只是一直在一个单独的代码行初始化之前,它是相同的。

其他提示

此WITH-行为从未改变。为了达到你的预期行为,你可以用这种方式更改代码:

    procedure TestIt;
    var
       myIntf: IMyIntf; 
    begin
      DoSomething;

      myIntf := TSomeObject.GetMyIntf
      DoStuff;
      DoMoreStuff;
      myIntf := nil; // <- here is where TSomeObject.Destroy called

      DoSomethingElse;
    end; 

,也可以做到这一点在过程:

procedure TestIt;

   procedure DoAllStuff;
   var
      myIntf: IMyIntf; 
   begin
      myIntf := TSomeObject.GetMyIntf
      DoStuff;
      DoMoreStuff;
   end;  // <- here is where TSomeObject.Destroy called

begin    
  DoSomething;
  DoAllStuff;
  DoSomethingElse;
end; 
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top