I am trying to use for in
to iterate a TObjectList
:
program Project1;
{$APPTYPE CONSOLE}
{$R *.res}
uses
System.SysUtils, Contnrs;
var
list: TObjectlist;
o: TObject;
begin
list := TObjectList.Create;
for o in list do
begin
//nothing
end;
end.
And it fails to compile:
[dcc32 Error] Project1.dpr(15): E2010 Incompatible types: 'TObject' and 'Pointer'
It seems as though Delphi's for in
construct does not handle the untyped, undescended, TObjectList
an as enumerable target.
How do i enumerate the objects in a TObjectList
?
My current code is:
procedure TfrmCustomerLocator.OnBatchDataAvailable(BatchList: TObjectList);
var
i: Integer;
o: TObject;
begin
for i := 0 to BatchList.Count-1 do
begin
o := BatchList.Items[i];
//...snip...where we do something with (o as TCustomer)
end;
end;
For no good reason, i was hoping to change it to:
procedure TfrmCustomerLocator.OnBatchDataAvailable(BatchList: TObjectList);
var
o: TObject;
begin
for o in BatchList do
begin
//...snip...where we do something with (o as TCustomer)
end;
end;
Why use an enumerator? Just cause.
The enumerator for TObjectList
is declared in TList
, which is the class from which TObjectList
is derived. The RTL doesn't bother to declare a more specific enumerator for TObjectList
. So you are left with the TList
enumerator. Which yields items of type Pointer
, that being the type of item held by TList
.
There are probably a few reasons why the RTL designers chose not to do anything with TObjectList
. For example, I posit the following potential reasons:
TObjectList
, like everything in Contnrs
is deprecated and rendered obsolete by the generic containers in Generics.Collections
. Why spend resource modifying an obsolete class.TObjectList
had an enumerator that yielded TObject
items, you'd still have to cast them. Would an enumerator that yielded TObject
really be that much more helpful?What should you do. An obvious choice is to use TList<T>
or TObjectList<T>
from Generics.Collections
. If you want to persist with TObjectList
, you could sub-class it and add an enumerator that yielded TObject
. In case you don't know how to do that, you can find out how to do so from the documentation. Or you could use the inherited enumerator and type cast the pointers that it yields.
It seems to me that since you are prepared to modify the code from an indexed for loop to a for in loop that implies that you are prepared to make non-trivial changes to the code. In which case the generic container would seem to be the obvious choice.