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.

Is this Spring4D list of pairs?
We’re not using Spring4D.
Are there any derived classes from TSelection or is there any functionality in TSelection not visible in the above example?
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.
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.
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?
Christopher Wosinski – That’s about it!
for non automatic freed objects TSelection could be a TArray
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.
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?
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.
I guess the items of that list have to be freed after the enumeration? That would be a point against arrays.
Uwe Raabe – It depends, but generally speaking – yes – the list has to be freed.
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
);
Perhaps this wrapper gets you on the track:
https://gist.github.com/anonymous/783814fba1a6c45dfc03
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.
Uwe Raabe you’re right, a sample for parameterized enumerators
http://www.thedelphigeek.com/2007/03/fun-with-enumerators-part-3.html
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.
Stefan Glienke – I agree 🙂 Unfortunately, I can’t introduce it as a quick fix.
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).
Stefan Glienke you are correct. I meant ienumerable.