Frage

Ich stolperte vor kurzem über ein Problem von einigen sehr alten Code verursacht ich schrieb, die offensichtlich, dass die Interface-Referenzen in einer with Anweisung verwendet wurde angenommen würde, sobald der with-Block bleibt freigegeben werden - ein bisschen wie eine implizite try-finally-Block (ähnlich wie C # 's using-Anweisung, wenn ich das richtig verstanden).

Anscheinend (in Delphi 2009) ist dies nicht (mehr?) Der Fall ist. Weiß jemand, wenn dies geschehen ist? Oder war mein Code einfach falsch zu beginnen?

Um zu klären, ist hier ein vereinfachtes Beispiel:

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

Jedes Mal, wenn jemand die alte „with ist böse“ Argument war immer das ein Beispiel begann ich im Sinn hatte, die mich gehen gehalten „Ja, aber ...“. Scheint, wie ich falsch war ... jemand bestätigen kann?

War es hilfreich?

Lösung

Die with erhaltene Wort in Pascal / Delphi ist nur für die leicht Zugriff auf die Mitglieder der Datensätze oder Objekte / Klassen (das heißt, um nicht zu erwähnen, den Datensatz des / Objekt / der Klasse Name) verwendet. Es ist sehr verschieden von der C # with, der Garbage Collection bezieht. Es hat sich in der Sprache Pascal existierte seit dem Tag records geboren wurden, Code Aufruf zu viele Datenelemente zu vereinfachen (damals einfach „Felder“ genannt).

Um es zusammenzufassen, hat with nichts mit Garbage Collection, der Freisetzung von Speicher oder Zerstörung von Objektinstanzen zu tun. Objekte, die vor initialisiert, in einem separaten Codezeile könnte das gleiche, es ist an der with Header konstruiert sind gerade.

Andere Tipps

Das MIT-Verhalten hat sich nie geändert. Um Ihr erwartetes Verhalten erreichen Sie können den Code auf diese Weise ändern:

    procedure TestIt;
    var
       myIntf: IMyIntf; 
    begin
      DoSomething;

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

      DoSomethingElse;
    end; 

oder Sie können es in der Prozedur tun:

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; 
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top