【问题标题】:How many objecttypes are inside my objectlist我的对象列表中有多少对象类型
【发布时间】:2014-03-27 22:31:37
【问题描述】:

使用 DELPHI 对象列表,我存储对 Tforms 类项的引用。在创建表单并将其插入该列表后,还会执行一些删除 .... 和其他处理步骤。 经过一段时间后,我需要评估我的对象列表的内容。

  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 而不是类型安全的通用 TObjectList<T>TList<T>
  • 我很好奇。为什么在一个对象列表中有多个相同表单的实例?
  • @Andy_D 我猜是因为它可能是一些编辑表单或类似的东西,您可以在其中编辑多个实例?
  • 请注意,您的程序已经保存了程序中所有表单的列表。见Screen.Forms
  • 再一次,你的最终目标是什么?您是否要根据表单类型对所有表单执行特殊操作?那么存在更好的解决方案来解决这个问题,但你必须提出正确的问题......

标签: delphi


【解决方案1】:

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

【讨论】:

    【解决方案2】:

    我能想到的最优雅的应该是这样的:

    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;
    

    【讨论】:

    • 这并没有真正完成所要求的。根据最后一段,第一个任务是确定列表中存在给定类的任何项。这会计算每个类的 多少,当它在第一次出现时足以停止时,会遍历整个列表。这也按类层次结构的叶类型进行分类,但is 运算符也会检查所有祖先类。第二个任务是确定列表中哪个项与请求的类匹配,第三个任务是找到该类的下一个项;这段代码也不行。
    • 他问“我的列表中还有多少 TMyform_1 类型的表单实例?”他展示的代码执行的是操作。但实际上我的回答是指他的要求(问题)而不是他展示的代码。也许他应该更清楚地说明他的要求。至于其他问题 - 我认为除非你想创建一些可笑的开销循环遍历列表是好的,所以这不需要在我的回答中提及。
    【解决方案3】:

    您可以为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;
    

    在您的应用程序中,您可以这样使用它

    var
      LItem : TMyForm_1;
    begin
      for LItem in MyObjectList.GetItemsByType<TMyForm_1> do
      begin
        // do something with LItem
      end;
    end;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-11-23
      • 2016-01-20
      • 1970-01-01
      • 1970-01-01
      • 2013-01-17
      • 2016-08-30
      • 1970-01-01
      • 2020-09-29
      相关资源
      最近更新 更多