Ian*_*oyd 6 delphi iterator for-loop for-in-loop listiterator
我试图for in
用来迭代一个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.
Run Code Online (Sandbox Code Playgroud)
它无法编译:
[dcc32错误] Project1.dpr(15):E2010不兼容的类型:'TObject'和'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;
Run Code Online (Sandbox Code Playgroud)
没有充分的理由,我希望将其改为:
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;
Run Code Online (Sandbox Code Playgroud)
为什么要使用枚举器?只是因为.
使用泛型,你可以有一个打字的对象列表(只是注意到评论,但无论如何不好完成)
如果您正在寻找一个使用TObjectList<T>
该原因的充分理由,那么它将为您节省大量代码中的类型转换
program Project1;
{$APPTYPE CONSOLE}
{$R *.res}
uses
System.SysUtils, Generics.Collections;
Type
TCustomer = class
private
public
//Properties and stuff
end;
var
list: TObjectlist<TCustomer>;
c: TCustomer;
begin
list := TObjectList<TCustomer>.Create;
for c in list do
begin
//nothing
end;
end.
Run Code Online (Sandbox Code Playgroud)
如何枚举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;
Run Code Online (Sandbox Code Playgroud)
枚举器的这种实现使用记录而不是类。这样做的优点是在进行for..in
枚举时不会在堆上分配额外的对象。
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;
Run Code Online (Sandbox Code Playgroud)
正如其他人所指出的,有一个泛型类是更好的选择,TObjectList<T>
.