Pregunta

Recientemente me topé con un problema causado por un código muy antiguo que escribí, que obviamente suponía que las referencias de interfaz utilizadas en una declaración with se liberarían tan pronto como con -block se deja - algo así como un implícito try-finally -block (similar a la declaración de de C # usando si entendí correctamente).

Aparentemente (en Delphi 2009) este no es el caso (¿ya no?). ¿Alguien sabe cuándo sucedió esto? ¿O fue mi código simplemente incorrecto para empezar?

Para aclarar, aquí hay un ejemplo simplificado:

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

Cada vez que alguien comienza el viejo " con es malo " argumento este fue siempre el único ejemplo que tenía en mente que me mantuvo en marcha "Sí, pero ...". Parece que me equivoqué ... ¿Alguien puede confirmar?

¿Fue útil?

Solución

La palabra preservada with en Pascal / Delphi solo se usa para acceder fácilmente a los miembros de registros u objetos / clases (es decir, para no mencionar el nombre del registro / objeto / clase). Es muy diferente del C # con que se relaciona con la recolección de basura. Ha existido en el lenguaje Pascal desde el día en que nacieron los records , para simplificar la llamada de código a muchos miembros de datos (en ese entonces simplemente se llamaban "campos").

Para resumir, with no tiene nada que ver con la recolección de basura, liberación de memoria o destrucción de instancias de objetos. Los objetos que se construyen en el encabezado with podrían haberse inicializado en una línea de código separada antes, es lo mismo.

Otros consejos

Este comportamiento WITH nunca ha cambiado. Para alcanzar su comportamiento esperado, puede cambiar su código de esta manera:

    procedure TestIt;
    var
       myIntf: IMyIntf; 
    begin
      DoSomething;

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

      DoSomethingElse;
    end; 

o puede hacerlo en el procedimiento:

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; 
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top