Search code examples
delphidelphi-7pascalwith-statement

If I create an object in a "with" clause, do I still need to free it?


In my source I see and use often a construction like:

with TSQLDataSet.Create(nil) do try
  //Dosomething, get a result from a query.    
finally
  Free;
end;

But I also often see the construction:

with TSQLDataSet.Create(nil) do begin
  //Dosomething, get a result from a query.    
end;

If I create objects with a with contruction, do I need to free them or is that automatic at the end of the with-block?


Solution

  • You need to free.

    Because Class.Create is just an expression, and Delphi cannot know which expression the resulting value came from.

    You can just read VCL sources - there is always explicit .Free.

    And you can think of non-object example:

    var r: record .... end;
    with r do begin
    ...
    end;
    

    If Delphi tried to free everything at with end - then it would try to free non-object ?

    with SomeObjectFactory.GetMeAnObject do begin
    ...
    end;
    

    Here you create object not by constructor, but by some function. And this function is not different from TLabel.Font or TDataSet.FieldByName. Should Delphi free it or not here ?

    To avoid the risky guesswork and keep it uniform - with is just with. It is just an alias. Nothing more. It was designed back in 1974 and is does not clone functionality of latest .Net/Scala Using(x){..} constructs.


    What you maybe saw were constructs like

    with TForm.Create(Application) do ...;
    with TLabel.Create(MainForm.Panel1) do ...;
    

    That is very different - that does insert newly created control as belonging to an owner. The owner would free all its owned components when it is freed itself. But that does not use Create(nil). And when it still does - then inside the with block you would see some explicit call, binding the object to some container/parent (though that is very fragile in case of exceptions between .Create and binding).