Reputation: 1502
I'm trying to go through a list of objects, but I just want to provide the interface implemented by my objects.
I have 2 cases: Just enumerating trough my list internally (which isn't that big of a problem, i could just use the object instead of the interface), and a property.
ITemplate = interface
...
end;
TTemplate = class (TInterfacedObject, ITemplate)
...
end;
TMyClass = class
strict private
FTemplates: TObjectList<TTemplate>;
function GetTemplates: IEnumerable<ITemplate>;
...
public
property Templates: IEnumerable<ITemplate> read GetTemplates;
...
procedure TMyClass.LoopTroughInternally;
var
template: ITemplate;
begin
for template in FTemplates do // isn't working, of course
foobar(template);
end;
function TMyClass.GetTemplates: IEnumerable<ITemplate>;
begin
// dunno what to do here...
end;
Is there a way to provide this enumerator without implementing a specific IEnumerable?
Upvotes: 1
Views: 149
Reputation: 612993
Taken at face value, you can just change the local variable template
to be of type TTemplate
and then you are done. If this code is internal then there's no real need to do anything else.
However, you seem to me to have bigger problems.
type
TTemplate = class(TInterfacedObject, ITemplate)
...
end;
....
FTemplates: TObjectList<TTemplate>;
This is a big mistake. When you inherit from TInterfacedObject
you are saying that the lifetime is managed by interface reference counting. That means that you must stop taking non-reference counted references. Because they are liable to become stale. And you are taking non-reference counted references when you use a TTemplate
reference. You compound matters by using TObjectList<T>
which is all about lifetime management.
The simple way to escape this is to use a list of interfaces rather than that TObjectList<T>
.
FTemplates: TList<ITemplate>;
Now at this point you are done and dusted because you can indeed write
for template in FTemplates do
where template
is ITemplate
.
Upvotes: 7