我试图用于迭代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.
它无法编译:
[dcc32 Error] Project1.dpr(15): E2010 Incompatible types: ‘TObject’ and ‘Pointer’
似乎Delphi的for in构造中没有处理无类型的,未说明的,TObjectList和可枚举的目标.
如何枚举TObjectList中的对象?
我现在应该做什么
我目前的代码是:
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;
没有充分的理由,我希望将其改为:
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;
为什么要使用枚举器?只是因为.
解决方法
How do i enumerate the objects in a TObjectList?
为了回答具体问题,这是引入枚举器的一个例子.
请注意,您必须创建TObjectList的后代才能添加GetEnumerator函数.您可以不使用类助手进行子类化,但我将其留作感兴趣的读者的练习.
type TObjectListEnumerator = record private FIndex: Integer; FList: TObjectList; public constructor Create(AList: TObjectList); function GetCurrent: TObject; function MoveNext: Boolean; property Current: TObject read GetCurrent; end; constructor TObjectListEnumerator.Create(AList: TObjectList); begin FIndex := -1; FList := AList; end; function TObjectListEnumerator.GetCurrent; begin Result := FList[FIndex]; end; function TObjectListEnumerator.MoveNext: Boolean; begin Result := FIndex < FList.Count - 1; if Result then Inc(FIndex); end; //-- Your new subclassed TObjectList Type TMyObjectList = class(TObjectList) public function GetEnumerator: TObjectListEnumerator; end; function TMyObjectList.GetEnumerator: TObjectListEnumerator; begin Result := TObjectListEnumerator.Create(Self); end;
枚举器的这种实现使用记录而不是类.这样做的优点是在执行枚举时不会在堆上分配额外的对象.
procedure TfrmCustomerLocator.OnBatchDataAvailable(BatchList: TObjectList); var o: TObject; begin for o in TMyObjectList(BatchList) do // A simple cast is enough in this example begin //...snip...where we do something with (o as TCustomer) end; end;
正如其他人所指出的,有一个泛型类是更好的选择,TObjectList< T>.