Domanda

Di recente mi sono imbattuto in un problema causato da un codice molto vecchio che ho scritto che ovviamente presupponeva che i riferimenti all'interfaccia utilizzati in un'istruzione con sarebbero stati rilasciati non appena con -block is left - un po 'come un implicito try-finally -block (simile al di C # usando -statement se ho capito bene).

Apparentemente (in Delphi 2009) questo non è (non più?) il caso. Qualcuno sa quando è successo? O il mio codice era semplicemente sbagliato all'inizio?

Per chiarire, ecco un esempio semplificato:

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

Ogni volta che qualcuno ha iniziato il vecchio " con è male " argomento questo è sempre stato l'unico esempio che avevo in mente che mi ha fatto andare avanti "Sì, ma ..." Sembra che mi sia sbagliato ... Qualcuno può confermare?

È stato utile?

Soluzione

Il con parola preservata in Pascal / Delphi viene utilizzato solo per accedere facilmente ai membri di record o oggetti / classi (cioè per non menzionare il nome del record / oggetto / classe). È molto diverso dal C # con relativo alla raccolta dei rifiuti. Esiste in lingua Pascal sin dal giorno in cui sono nati i record , per semplificare la chiamata del codice a molti membri dei dati (all'epoca semplicemente chiamati "campi").

Per riassumere, con non ha nulla a che fare con la garbage collection, il rilascio di memoria o la distruzione di istanze di oggetti. Gli oggetti costruiti nell'intestazione con avrebbero potuto essere inizializzati in una riga di codice separata prima, è lo stesso.

Altri suggerimenti

Questo comportamento WITH non è mai cambiato. Per raggiungere il comportamento previsto, puoi modificare il codice in questo modo:

    procedure TestIt;
    var
       myIntf: IMyIntf; 
    begin
      DoSomething;

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

      DoSomethingElse;
    end; 

oppure puoi farlo nella procedura:

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; 
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top