Interfaces and self-destruction

Interfaces and self-destruction

I need the guidance of the gurus here. I’ve seen this mentioned before, but I can’t recall where.

I have a need for enumerating a list subset and I am wondering how I can do this while at the same time eliminating the housekeeping?

type

   TSelection = class(TList<TPair>);

Basically, I have various classes that I would like to return variations on a TSelection from a function.

type

  TSomeClass = class

     function AllActive(const filtervalue:sometype): TSelection;

  end;

var

  item: TPair;

begin

  for item in SomeClassInstance.AllActive(aFilter)

  do begin

     // something happens that concerns item

  end;

  // returned TSelection is automagically free’d here

end;

I actually want to use this in multiple levels, and there will be a multitude of TSelection returning functions – hence the desire for automated housekeeping.  Performance is not my primary concern – only flexibility and easy to read code.

Pointers to examples would be much appreciated – but I’d prefer not to pull in an entire class library – just a bare bone minimum.

21 thoughts on “Interfaces and self-destruction


  1. Are there any derived classes from TSelection or is there any functionality in TSelection not visible in the above example?


  2. Uwe Raabe – TSelection doesn’t exist yet.  I am looking for a method that lets me return lists containing objects that are either referenced and not freed on scope exit,  or created on demand, and then freed on scope exit.


  3. If instead of TSelection it was ISelection, and the backing class was TInterfacedObject, that would work… but I think you know that so I’m confused and not sure what you’re asking. What about interfaces and self-destruction are you seeking guidance about?


    Or AllActive could be a class field, if you guaranteed only one instance of code was accessing it at a time? Then the owner object would look after deleting it.


  4. Hmm..I don’t know if I get you right.


    Try to return ISelection instead of the concrete TSelection in AllActive.


    Declaration would look something like that


    ISelection = interface


      function GetEnumerator: TEnumerator<TPair>


    end;


    TSelection = class(TInterfacedObject, ISelection)


    private


      FList: TList<TPair>; // created in constructor, destroyed in destructor


    public


      function GetEnumerator: TEnumerator<TPair>; //returns FList.GetEnumerator


     // + ..some add, delete, etc. methods that work on FList


    end;


    If you’d do it like this then your AllActive method can create a TSelection instance and fill it with pairs before returning it. After executing the for-in-loop TSelection is going to be destroyed. Is that what you are looking for?


  5. Whatever you do, don’t try to implement the supplied IList. It’s a waste of time. It was designed for Delphi.NET and assumes a type system rooted in TObject.


  6. If you only care about for..in, then that does the housekeeping for you if the enumerator is an object instance. Alternatively return a record type?


  7. Asbjørn Heid – I do only care for the enumerator – but – the objects that I want to enumerate, doesn’t necessarily exist as single entities or in an easily enumerable list, hence I need to create them on the fly.  They have to be constructed by crawling multidimensional data structures, possibly reordered, then enumerated.


  8. BTW you can also make something like


    SomeClasseInstance.ForEachActive(


      aFilter,


      procedure (Item: TPair)


      begin


       …


      end


    );


    that can be used to build a list


    List := TList.Create;


    SomeClasseInstance.ForEachActive(


      aFilter,


      procedure (Item: TPair)


      begin


        List.Add(Item);


      end


    );


  9. Paul TOTH – That’s what we’re currently using, and the anon method variable capture is creating all sorts of issues, which go unwarned by the compiler.


  10. Lars Fosdal “We’re not using Spring4D.” That is the issue :p


    Kenneth Cochran I guess you mean IEnumerable. There is no IList in the RTL.


  11. Lars Fosdal Id’ make TSelection a record, and make the enumerator it creates in GetEnumerator free the elements in its destructor.


    If you want TSelection to contain objects which you don’t want to change to interfaces directly, just use a “lifetime manager” interface instance for each one (ie a simple interface which implementation takes an object instance and frees it in its destructor).

Leave a Reply