Delphi: С каких это пор ссылки на интерфейсы больше не выпускаются в конце блока with?

StackOverflow https://stackoverflow.com/questions/1233773

Вопрос

Недавно я наткнулся на проблему, вызванную каким-то очень старым кодом, который я написал, который, очевидно, предполагал, что ссылки на интерфейсы, используемые в операторе with , будут освобождены, как только с -блок слева - вроде как неявный try-finally -блок (аналогично с использованием -статации в C #, если я правильно понял).

По-видимому (в 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 в Pascal / Delphi используется только для легкого доступа к членам записей или объектов / классов (то есть, чтобы не упоминать имя записи / объекта / класса). Это очень отличается от C # с , что касается сборки мусора. Он существует на языке Pascal со дня рождения records , чтобы упростить вызов кода для многих членов данных (тогда это просто называлось " fields ").

Подводя итог, можно сказать, что 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