Delphi:如何使用TObjectList <t>?</t>

时间:2009-11-02 11:21:28

标签: delphi generics tobjectlist

我需要了解如何使用通用Delphi 2009 TObjectList。我的非TObjectList尝试看起来像是

TSomeClass = class(TObject)
private
  FList1: Array of TList1;
  FList2: Array of TList2;
public
  procedure FillArray(var List: Array of TList1; Source: TSource); Overload;
  procedure FillArray(var List: Array of TList2; Source: TSource); Overload;
end;

此处,TList1TList2会继承相同的构造函数constructor TParent.Create(Key: string; Value: string);。但是,由于不同的专业化(例如,不同的私有字段),它们将不是同一类型。所以我必须写两个几乎相同的填充方法:

procedure TSomeClass.FillArray(var List: Array of TList1; Source: TSource);
begin
  for i := 0 to Source.List1.Count - 1 do begin
    SetLength(List, Length(List) + 1);
    List[i] := TList1.Create(Source.List1[i].Key, Source.List1[i].Value);
  end;
end;

FillArray(List: Array of TList2; Source: TSource);相同,但整个TList1替换为TList2除外。据我了解,使用TObjectList和单一填充方法可以巧妙地避免这种情况;但是,我不知道如何解决这个问题。有没有人对此有一些好的指示?谢谢!

3 个答案:

答案 0 :(得分:2)

您无法通过使用通用列表来缩减它,因为泛型的类型是类定义的一部分。因此TObjectList<TMyClass1>TObjectList<TMyClass2>不同(并且不相容)。使用通用列表优于普通TList / TObjectList的主要好处是改进了类型安全性,减少了强制转换和更清晰的代码。

此外,如果您正在使用键/值对,是否将它们放入列表中,然后通过搜索键并返回相关值来检索它们?如果是这样,请查看Generics.Collections中的TDictionary。它是一个通用的键/值哈希表,可以为您大大简化此过程。

答案 1 :(得分:0)

Generics.Collections.TObjectList上的官方Embarcadero文档Wiki包含TObjectList in action的简单代码示例。

我不确定问题究竟是什么,但为了解决TObjectList的广泛使用,TObjectList的示例初始化代码可能如下所示:

var
  List: TObjectList<TNewObject>;
  Obj: TNewObject;
begin
  { Create a new List. }
  List := TObjectList<TNewObject>.Create();

  { Add some items to the List. }
  List.Add(TNewObject.Create('One'));
  List.Add(TNewObject.Create('Two'));

  { Add a new item, but keep the reference. }
  Obj := TNewObject.Create('Three');
  List.Add(Obj);

example code应该让你知道TObjectList可以做什么但是如果我已经正确理解了这个问题,你似乎希望能够将多个类类型添加到单个实例中TObjectList? TObjectList只能使用单一类型启动,因此如果您使用Interface或Abstract类启动TObjectList可能会更好,该类由您希望添加到其中的所有类共享。

使用TObjectList与创建自己的OwnsObjects相比,一个重要的区别是TObjectList属性的存在,它告诉{{3}}它是否拥有您添加到其中的对象,因此它是否应该自己管理它们。

答案 2 :(得分:0)

这样的东西?

TSomeClass = class
private
  FList1: TArray<TList1>;
  FList2: TArray<TList2>;
public
  procedure FillArray<T>(var List: TArray<T>; Source: TSource);
end;

procedure TSomeClass.FillArray<T>(var List: TArray<T>; Source: TSource);
begin
  for i := 0 to Source.List1.Count - 1 do begin
    SetLength(List, Length(List) + 1);
    List[i] := T.Create(Source.List1[i].Key, Source.List1[i].Value);
  end;
end;

这或类似的东西应该做你想要的,afaict。