如何在TObjectList中做?

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)

为什么要使用枚举器?只是因为.

Teu*_*onk 5

使用泛型,你可以有一个打字的对象列表(只是注意到评论,但无论如何不好完成)

如果您正在寻找一个使用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)


LU *_* RD 4

如何枚举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>.