Some time ago, we discussed the Free/DisposeOf issue of new ARC Delphi objects in the Delphi plus group.
The problem is that Free() does not call the destructor directly any more. It sets the object reference to nil instead. When the reference count is 0, the destructor is called.
I am among those who don’t like this new compiler feature. Free could just do what DisposeOf does (call destructor and set the object to zombie state). So there is basically no need of DisposeOf.
Now, we have another argument for the DisposeOf/Free futility: under some circumstances, pending references can be created by the compiler itself (when the object reference is passed to the Result variable but not used at all). The programmer thinks that there are no references left and the destructor should get called but no, the destructor is not called indeed.
The same behaviour can be observed on desktop compilers too with all reference-counted types (strings, interfaces, dynamic arrays) but none of those types rely on an explicit destructor call, so it does not really matter.
Link to the QC: http://qc.embarcadero.com/wc/qcmain.aspx?d=124017
Honestly, I just don’t see the point why I should call DisposeOf() now everywhere where I have called Free() for so many years…
Sample code to reproduce (call TestReferenceBug()):
type TMyObject = class(TInterfacedObject) public destructor Destroy; override; end; destructor TMyObject.Destroy; begin ShowMessage('TMyObject.Destroy'); inherited; end; function MyFunc(const aObj: TObject): TObject; begin Result := aObj; end; procedure TestReferenceBug; var xObj: TObject; begin xObj := TMyObject.Create; try MyFunc(xObj);//"virtual" reference is created here finally xObj.Free;//xObj.Destroy is not called!!! end; ShowMessage('After try-finally-end'); end;//"virtual" reference is destroyed here -> call xObj.Destroy