Delphi 我的objectlist中有多少ObjectType

Delphi 我的objectlist中有多少ObjectType,delphi,Delphi,我使用DELPHI对象列表存储对Tforms类项的引用。在创建表单并将表单插入该列表后,还有一些表单被删除。。。。并执行其他处理步骤。 之后,我需要评估objectlist的内容 aForm1 : TMyForm_1 ; aForm2 : TMyForm_1 ; aForm3 : TMyForm_1 ; MyObjectList := TObjectList.create; .... MyObjectList.add(aForm1) ; // and als

我使用DELPHI对象列表存储对Tforms类项的引用。在创建表单并将表单插入该列表后,还有一些表单被删除。。。。并执行其他处理步骤。 之后,我需要评估objectlist的内容

  aForm1 : TMyForm_1 ;
  aForm2 : TMyForm_1 ;
  aForm3 : TMyForm_1 ;

  MyObjectList := TObjectList.create; 

  ....  
  MyObjectList.add(aForm1) ;  //  and also the other forms , many time each ...
我的列表中还有多少来自TMyform_1类型的表单实例? 循环所有列表元素并检查类类型是我解决该任务的想法

for i := 0 ....    
if (MyObjectList.items[i] is  TMyForm_1) ...
有没有更优雅的方法来解决这个问题?
首先我只需要知道我的列表中有一个TMyForm_1类型,然后给我第一个位置,最后从这个位置。。。转到此列表中的下一个元素。

TObjectList不提供任何基于容器成员的运行时类型返回信息的方法。您必须使用
is
操作符编写自己的功能。

我能想到的最优雅的方法是:

uses
  Generics.Collections;

var
  dict: TDictionary<TClass,Integer>;
  obj: TObject;
  i: Integer;
begin
  // ...

  for obj in MyObjectList do
    if dict.TryGetValue(obj.ClassType, i) then
      dict[obj.ClassType] := i + 1
    else
      dict.Add(obj.ClassType, 1);

  // ...
end;
使用
仿制药。收藏;
变量
dict:t词典;
对象:对象;
i:整数;
开始
// ...
对于MyObjectList中的obj,请执行以下操作:
如果dict.TryGetValue(obj.ClassType,i),则
dict[obj.ClassType]:=i+1
其他的
dict.Add(obj.ClassType,1);
// ...
结束;

您可以为
TObjectList
编写一个类帮助器,并添加一个函数,返回给定类型的项数组

type
  TObjectListHelper = class helper for TObjectList
    function GetItemsByType<T : class> : TArray<T>;
  end;

  { TObjectListHelper }

function TObjectListHelper.GetItemsByType<T> : TArray<T>;
var
  LIdx : Integer;
  LItem : TObject;
  LCount : Integer;
begin
  SetLength( Result, Self.Count );
  LCount := 0;
  for LIdx := 0 to Self.Count - 1 do
  begin
    LItem := Self.Items[LIdx];

    if LItem is T then
    begin
      Result[LCount] := LItem as T;
      Inc( LCount );
    end;
  end;
  SetLength( Result, LCount );
end;
类型
TObjectListHelper=TObjectList的类帮助器
函数GetItemsByType:TArray;
结束;
{TObjectListHelper}
函数TObjectListHelper.GetItemsByType:TArray;
变量
LIdx:整数;
LItem:TObject;
l计数:整数;
开始
SetLength(结果、自计数);
l计数:=0;
对于LIdx:=0到Self.Count-1 do
开始
LItem:=Self.Items[LIdx];
如果LItem是T,那么
开始
结果[LCount]:=LItem作为T;
公司(LCount);
结束;
结束;
设置长度(结果,LCount);
结束;
在应用程序中,您可以这样使用它

var
  LItem : TMyForm_1;
begin
  for LItem in MyObjectList.GetItemsByType<TMyForm_1> do
  begin
    // do something with LItem
  end;
end;
var
LItem:TMyForm_1;
开始
对于MyObjectList.GetItemsByType do中的LItem
开始
//用LItem做点什么
结束;
结束;

您使用传统的
TObjectList
而不是类型安全的通用
TObjectList
TList
有什么好的理由吗?我很好奇。为什么在一个对象列表中会有同一表单的多个实例?@Andy_D我猜是因为它可能是某种编辑表单或类似的表单,您可以编辑多个实例?请注意,您的程序已经在程序中保留了所有表单的列表。再问一次,你的最终目标是什么?是否要根据表单类型对所有表单执行特殊操作?还有更好的解决方案,但你必须提出正确的问题……这并不能真正实现你的要求。根据最后一段,第一项任务是确定列表中是否存在给定类的任何项。这会计算每个类中有多少个类,当它在第一次出现时就足以停止时,会遍历整个列表。这也会根据类层次结构的叶类型进行分类,但是
is
操作符也会检查所有祖先类。第二个任务是确定列表中的哪个项与请求的类匹配,第三个任务是查找该类的下一项;这段代码两者都没有。他问“我的列表中还有多少来自TMyform_1类型的表单实例?”他显示的代码执行了is操作。但实际上我的回答是指他的要求(问题),而不是他展示的代码。也许他应该更清楚地说明他的要求。至于其他问题——我认为,除非你想创造一些荒谬的开销,否则在列表中循环是可以的,所以这不需要在我的回答中提及。