Question

Je suis récemment tombé sur un problème causé par un très vieux code que j'ai écrit et qui supposait évidemment que les références d'interface utilisées dans une instruction avec seraient publiées dès que le avec -block est laissé - un peu comme un bloc try-finally implicite (similaire au de C # utilisant -atatement si j'ai bien compris).

Apparemment (dans Delphi 2009), ce n’est pas (plus?) le cas. Est-ce que quelqu'un sait quand c'est arrivé? Ou mon code était-il tout simplement faux au début?

Pour clarifier, voici un exemple simplifié:

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

Chaque fois que quelqu'un a lancé l'ancien " avec , c'est diabolique " Cet argument a toujours été le seul exemple auquel je pensais qui me faisait continuer "Oui, mais ...". On dirait que je me suis trompé ... Quelqu'un peut-il confirmer?

Était-ce utile?

La solution

Le mot avec préservé dans Pascal / Delphi est uniquement utilisé pour accéder facilement aux membres des enregistrements ou aux objets / classes (c'est-à-dire afin de ne pas mentionner le nom de l'objet / de la classe / de l'enregistrement). C'est très différent du C # avec qui concerne la récupération de place. Il existait en langage Pascal depuis la naissance de enregistrements , pour simplifier l'appel de code à de nombreux membres de données (autrefois simplement appelés "champs").

Pour résumer, avec n'a rien à voir avec la récupération de place, la libération de mémoire ou la destruction d'instances d'objet. Les objets construits dans l'en-tête avec pourraient simplement avoir été initialisés dans une ligne de code distincte auparavant, c'est la même chose.

Autres conseils

Ce comportement WITH n'a jamais changé. Pour obtenir le comportement attendu, modifiez votre code de la manière suivante:

    procedure TestIt;
    var
       myIntf: IMyIntf; 
    begin
      DoSomething;

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

      DoSomethingElse;
    end; 

ou vous pouvez le faire en procédure:

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; 
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top