use*_*674 5 delphi generics tlist
我想在Delphi XE5中使用带有子列表的通用TList记录:
type
TMyRecord=record
Value1: Real;
SubList: TList<Integer>;
end;
TMyListOfRecords=TList<TMyRecord>;
var
MyListOfRecords: TMyListOfRecords;
Run Code Online (Sandbox Code Playgroud)
无法分配记录字段:
MyListOfRecords[0].Value1:=2.24;
Run Code Online (Sandbox Code Playgroud)
要么
MyListOfRecords[0].SubList:=TList<Integer>.Create;
Run Code Online (Sandbox Code Playgroud)
将导致编译器"左侧无法分配"错误.
另请参见:如何修改TList <record>值?
以下解决方法有效:
AMyRecord:=MyListOfRecords[0];
AMyRecord.Value1:=2.24;
AMyRecord.SubList:=TList<Integer>.Create;
AMyRecord.SubList.Add(33);
MyListOfRecords[0]:=AMyRecord;
Run Code Online (Sandbox Code Playgroud)
由于性能问题,我想避免将数据复制到临时AMyrecord.我宁愿直接访问记录字段和子列表.
处理这个问题的最佳方法是什么?
该列表通过List属性公开其内部存储(动态数组).所以你可以写:
MyListOfRecords.List[0].Value1 := 2.24;
Run Code Online (Sandbox Code Playgroud)
与具有价值副本的替代方案相比,这是否会在性能方面产生任何可衡量的差异,我无法分辨.值得检查一下.
正如@LURD所说,List返回内部存储.这可能不仅仅是Count元素.具体来说它有Capacity元素.所以,如果你使用它,你必须访问使用数组索引的元素,在元素0来Count-1.还要记住,对列表大小的修改可能涉及重新分配,因此内部存储可能会移动.您接受的任何引用List仅在下次重新分配之前有效.
这些警告应该告诉您,List如果性能限制需要,您只考虑使用.即使这样,也要谨慎使用它.
在我的代码库中,我有一个替代,TList<T>其Items[]属性返回一个指向该元素的指针.容器仍然存储为动态数组,以实现高效的内存布局.我更喜欢这个List属性的选项,因为我觉得它导致更清晰的代码.
好的,你要求查看我的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;
Run Code Online (Sandbox Code Playgroud)
现在,需要一些解释.基类,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;
Run Code Online (Sandbox Code Playgroud)
我的实现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;
Run Code Online (Sandbox Code Playgroud)
如果你想要一套比Delphi更丰富的容器,你可能会关注Spring4D.虽然我不确定他们是否有类似我的容器返回引用.