代码之家  ›  专栏  ›  技术社区  ›  Oliver Giesen

Delphi:什么时候接口引用不再在WITH块的末尾释放?

  •  4
  • Oliver Giesen  · 技术社区  · 15 年前

    我最近偶然发现了一个问题,它是由我编写的一些非常老的代码引起的,这显然是假设在 with 声明将在 具有 -块是左的-有点像隐式的 try-finally -块(类似于C using -如果我理解正确的话)。

    显然(在德尔福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
    

    每当有人开始老的时候” 具有 “邪恶”的论点,这一直是我脑海中的一个例子,它让我继续“是的,但是……”。好像我错了…有人能证实吗?

    2 回复  |  直到 14 年前
        1
  •  17
  •   Roee Adler    15 年前

    这个 with pascal/delphi中的保留字仅用于轻松访问记录或对象/类的成员(即,为了不提及记录/对象/类的名称)。它和C非常不同# 具有 与垃圾收集有关。它从那天起就以帕斯卡语存在。 records 为了简化对许多数据成员的代码调用(当时简单地称为“字段”)。

    总结, 具有 与垃圾收集、释放内存或销毁对象实例无关。在 具有 header以前可能只是在单独的代码行中初始化的,它是相同的。

        2
  •  3
  •   Lars Truijens    15 年前

    这种行为从未改变。要达到预期的行为,可以通过以下方式更改代码:

        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;