function returning TInterfacedObject

It is convenient, in my code, for me to have a function returning an instance of an object without me having to worry about managing that instance .. in other words, I am looking for garbage collection.

I don't know much about interfaces, but I thought the following might work
  function getAsString: String;
  property AsString : String read getAsString;

function Tfred.getAsString: String;
result := inttostr(refCount);

 Ttom = class
  function aFred: Tfred;
end; // Ttom

 function Ttom.aFred: Tfred;
  result :=Tfred.create;
  // never cleaned up

or even
function myFred:Tfred; begin result:=Tfred.create; end;

procedure TForm1.btnTestReferencecountingClick(Sender: TObject);
var k: integer; tom : TTom;

tom := Ttom.create;
for k:=1 to 100 do begin
dsmemo1.out([tom.afred.AsString, myFred.AsString]);

Is this a correct usage of TinterfacedObject?

I don't think reference counting is going to come into it, but will all my instances of Tfred be released at the end of the calling procedure??

Also, I don't understand how the cleanup can happen correctly without Delphi maintaining some sort of internal list (in which case there would be a hidden overhead, compared to managing the lifetimes yourself). I understand the reference count is maintained with the object, but somehow - at run time - the app must tell the object that it is no longer in scope ..

enlightenment and code correction sought, please
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Hi, Mutley :)
Your code will work, but you still need to free your objects, since reference counting is used only to interfaces.
TInterfaceObject is helper object which impelements AddRef, Release methods of IInterface. You should declare and implement your IFred interface to use reference counting..
here will be reworked code:

  TForm1 = class(TForm)
    Button1: TButton;
    Memo1: TMemo;
    procedure Button1Click(Sender: TObject);

  IFred = interface
    function AsString: string;

  TFred = class(TInterfacedObject, IFred)
    destructor Destroy; override;
    function AsString: string;

  TTom = class
    function GetFred: IFred;

  Form1: TForm1;


{$R *.dfm}

{ TFred }

function TFred.AsString: string;
  Result := inttostr(RefCount);

destructor TFred.Destroy;

// simple function to get Fred
function GetFred: IFred;
  Result := TFred.Create;

procedure TForm1.Button1Click(Sender: TObject);
  Tom: TTom;
  i: integer;
  tom := TTOm.Create;
    for i := 0 to 10 do
     // scope of IFred is limited only to this line
     //(actually there is two separate TFred interface instances used)
      Memo1.Lines.Add(Tom.GetFred.AsString + '; '+ GetFred.AsString);

{ TTom }

function TTom.GetFred: IFred;
  Result := TFred.Create;

wbr, mo.
Delphi's reference counting is, in my experience, not useful.  If you add an interface object to a list, for example, the reference count is not updated, so your objects may disappear "randomly", or fail yto be garbage collected and the reason not be apparent.
Even in Java, you have to pay careful attention to the GC and the memory model, or it works against you rather than for you.  Java uses a access graph rather than a reference count, which is mroereliable, and even it has problems.

In Delphi, it is far better to ensure that you free everything than to depend on the GC model.
Python 3 Fundamentals

This course will teach participants about installing and configuring Python, syntax, importing, statements, types, strings, booleans, files, lists, tuples, comprehensions, functions, and classes.

Delphi does not manage a list.  Every call to the object through the TInterfacedObject code checks reference count.  If reference count is zero then it frees the object.

This leads to interesting effects if you create an object, add it to a list, and then attempt to perform some operations against it.  The first operation succeeds, but it also frees the object.  The second operation fails randomly because the object has been freed, and its memory (which you are still pointing at) is in an indeterminate state.

The overhead of this is huge.  In the same code, going through both the "interface" model and the pure inheritance model, the interface model was able to perform 5,000 operations per second.  The identical code, refactored to use the pure inheritance model, was able to perform 12,000,000 operations per second.

All tests were performed under Windows 98 on the same 800 MHz machine.  At the higher speed, a complete regression test takes roughly 11 hours, so you can see why I threw out the interface model once I did force it to work.

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
Mutley2003Author Commented:

ok, I am convinced. With only a little more work I can use the traditional approach, and with results like the ones you have obtained, I see no reason to venture into the uncharted waters of interfaces and garbage collection

The implementation of the "interface" concept in Delphi was tied in to COM.  This was a deliberate decision because of the way that Windows architecture was going.  It is not fair to write off the interfaces approach entirely

Delphi Interfaces are still useful in two places:
1. any interaction through the COM or ActiveX API - say a DLL that implements a COM object for use by an outsode program
2. operations where performance is not an issue, and you can control the refernces yourself - for example the DUnit testing framework

In Java, the designers did not labour under the need to conform to a M$oft architecture direction of the week, so interfaces are implemented as a parallel VMT (array of pointers) and are very light weight.

Interfaces and garbage collection should be considered as two independent questions, even though they have been rolled together in the Delphi model.  I think that the Delphi architects recognize this flaw, but too much code has been written for this blurred paradigm for them to arbitrarily change it and break their customers' code base.
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today

From novice to tech pro — start learning today.