Delphi: как использовать TObjectList<T>?
Мне нужно понять, как использовать общий 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;
Вот, 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 ответа
Вы не сможете сжать это с помощью универсального списка, так как тип универсального является частью определения класса. Так что TObjectList<TMyClass1>
отличается от (и несовместим с) TObjectList<TMyClass2>
, Основным преимуществом использования общих списков по сравнению с обычным TList/TObjectList является улучшенная безопасность типов, с меньшим количеством приведений и более чистым кодом.
Кроме того, если вы используете пары ключ / значение, вы помещаете их в список, а затем извлекаете их, ища ключ и возвращая соответствующее значение? Если это так, взгляните на TDictionary в Generics.Collections. Это универсальная хеш-таблица ключей / значений, которая значительно упростит вам этот процесс.
Что-то вроде этого?
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;
Это или что-то вроде этого должно делать то, что вы хотите, ааакт.
Официальная вики-документация Embarcadero на http://docwiki.embarcadero.com/VCL/en/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, владеет ли он объектами, которые вы добавляете в него, и, следовательно, следовательно, должен ли он сам управлять их освобождением.