Delphi: как использовать TObjectList <T>? - PullRequest
2 голосов
/ 02 ноября 2009

Мне нужно понять, как использовать универсальный Delphi 2009 TObjectList. Моя не-1002 * попытка выглядела как

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;

Здесь TList1 и TList2 наследуют один и тот же конструктор 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 ]

2 голосов
/ 02 ноября 2009

Вы не сможете сжать это с помощью универсального списка, так как тип универсального является частью определения класса. Таким образом, TObjectList<TMyClass1> отличается (и несовместимо) с TObjectList<TMyClass2>. Основным преимуществом использования общих списков по сравнению с обычными TList / TObjectList является повышенная безопасность типов, меньшее количество приведений и более чистый код.

Кроме того, если вы используете пары ключ / значение, вы помещаете их в список, а затем извлекаете их, ища ключ и возвращая соответствующее значение? Если это так, взгляните на TDictionary в Generics.Collections. Это универсальная хеш-таблица ключей / значений, которая значительно упростит вам этот процесс.

0 голосов
/ 02 ноября 2009

Как то так?

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;

Это или что-то вроде этого должно делать то, что вы хотите, ага.

0 голосов
/ 02 ноября 2009

Официальная вики-документация Embarcadero на Generics.Collections.TObjectList содержит простой пример кода TObjectList в действии .

Я точно не знаю, к чему ведет этот вопрос, но для решения широкого использования 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);

Пример кода должен дать вам представление о том, что может делать TObjectList, но если я правильно понял вопрос, кажется, вы хотели бы иметь возможность добавить более одного типа класса к один экземпляр TObjectList ? TObjectList может быть инициирован только с одним типом, поэтому было бы лучше, если бы вы инициировали TObjectList с помощью класса Interface или Abstract, который является общим для всех классов, которые вы хотите добавить в него.

Одно важное отличие при использовании TObjectList по сравнению с созданием собственного - это наличие свойства OwnsObjects , которое сообщает TObjectList , владеет ли оно объектами, которые вы добавьте к этому и, следовательно, следовательно, должен ли он сам освободить их.

...