Delphi:从什么时候接口引用不再在with-block结束时释放?

时间:2009-08-05 14:50:38

标签: delphi interface delphi-2009 reference-counting with-statement

我最近偶然发现了由我编写的一些非常旧的代码引起的问题,这显然假设with语句中使用的接口引用将在with - 块被释放后立即释放 - 有点像隐式try-finally - 块(类似于C#的using - 语句,如果我理解正确的话)。

显然(在Delphi 2009中)这不是(不再是?)的情况。有谁知道这发生的时间?或者我的代码开始时是完全错误的?

澄清一下,这是一个简化的例子:

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是邪恶的”论证时,这总是我心中的一个例子让我继续“是的,但......”。好像我错了......任何人都可以确认吗?

2 个答案:

答案 0 :(得分:17)

Pascal / Delphi中的with保留字仅用于轻松访问记录或对象/类的成员(即为了不提记录/对象/类的名称)。它与C#with与垃圾收集有很大不同。自records出生之日起,它就以Pascal语言存在,以简化代码调用许多数据成员(当时简称为“字段”)。

总而言之,with与垃圾收集,内存释放或对象实例的破坏无关。在with标题处构造的对象之前可能已经在单独的代码行中初始化,它们是相同的。

答案 1 :(得分:3)

此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;