Список предоставляет свое внутреннее хранилище, которое представляет собой динамический массив, через List
собственность. Итак, вы можете написать:
MyListOfRecords.List[0].Value1 := 2.24;
Влияет ли это на какую-либо измеримую разницу в производительности по сравнению с альтернативой с копиями значений, я не могу сказать. Стоило бы это проверить.
Как правильно говорит @LURD, List
возвращает внутреннюю память. И это может иметь более Count
элементов. В частности, он имеет Capacity
элементов. Итак, если вы используете его, вы должны получить доступ к элементам, используя индексацию массива, по элементам с 0
по Count-1
. Помните также, что изменение размера списка может привести к перераспределению и, следовательно, к перемещению внутренней памяти. Любая ссылка на List
действительна только до следующего перераспределения.
Эти предупреждения должны подсказать вам, что вы можете использовать List
только в том случае, если этого требуют ограничения производительности. И даже в этом случае используйте его экономно.
В моей кодовой базе есть альтернатива TList<T>
, чье свойство Items[]
возвращает указатель на элемент. Контейнер по-прежнему хранится как динамический массив для эффективного распределения памяти. Я предпочел эту опцию свойству List
, потому что чувствовал, что это приводит к более чистому коду.
Хорошо, вы просили взглянуть на мой класс списка, который возвращает указатели на элементы. Вот:
type
TReferenceList<T> = class(TBaseValueList<T>)
type
P = ^T;
private
function GetItem(Index: Integer): P;
public
property Items[Index: Integer]: P read GetItem; default;
public
// .... helper types for enumerators excised
public
function GetEnumerator: TEnumerator;
function Enumerator(Forwards: Boolean): TEnumeratorFactory;
function ReverseEnumerator: TEnumeratorFactory;
function IndexedEnumerator: TIndexedEnumeratorFactory;
end;
Нужны пояснения. Базовый класс, TBaseValueList<T>
, является моей альтернативой TList<T>
. Вы можете заменить TList<T>
, если хотите. Нет, потому что в моем базовом классе нет свойства Items
. Это потому, что я хочу, чтобы специализированные классы представили его. Другая моя специализация:
type
TValueList<T> = class(TBaseValueList<T>)
private
function GetItem(Index: Integer): T;
procedure SetItem(Index: Integer; const Value: T);
public
property Items[Index: Integer]: T read GetItem write SetItem; default;
end;
Реализация моего TBaseValueList<T>
довольно очевидна. Очень похоже на TList<T>
. Я не думаю, что вам действительно нужно видеть какую-либо реализацию. Это все очень очевидно.
В качестве простого способа получить ссылку на элемент вы можете обернуть List
следующим образом:
type
TMyList<T> = class(TList<T>)
public
type
P = ^T;
private
function GetRef(Index: Integer): P;
public
property Ref[Index: Integer]: P read GetRef;
end;
function TMyList<T>.GetRef(Index: Integer): P;
begin
Result := @List[Index];
end;
Если вам нужен более богатый набор контейнеров, чем в Delphi, вы можете обратить внимание на Spring4D. Хотя я не уверен, есть ли у них что-то вроде моего контейнера, который возвращает ссылки.
person
David Heffernan
schedule
06.03.2014