具有子列表的通用TList记录? [英] generic TList of records with a sub list?

查看:177
本文介绍了具有子列表的通用TList记录?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想在Delphi XE5中使用具有子列表的通用TList记录:

 键入
TMyRecord = record
Value1:Real;
子列表:TList< Integer> ;;
结束

TMyListOfRecords = TList< TMyRecord> ;;

var
MyListOfRecords:TMyListOfRecords;

无法对记录的字段进行分配:

  MyListOfRecords [0] .Value1:= 2.24; 

  MyListOfRecords [0] .SubList:= TList< Integer> .Create; 

将导致编译器左侧无法分配错误。



另请参见:如何修改TList< record>值?



以下解决方法有效:

  AMyRecord:= MyListOfRecords [0]; 
AMyRecord.Value1:= 2.24;
AMyRecord.SubList:= TList< Integer> .Create;
AMyRecord.SubList.Add(33);
MyListOfRecords [0]:= AMyRecord;

由于性能问题,我想避免将数据复制到临时AMyrecord。我宁愿直接访问记录字段和子列表。



最好的处理方式是什么?

解决方案

该列表通过 列表 属性。所以你可以写:

  MyListOfRecords.List [0] .Value1:= 2.24; 

与价值副本的替代品相比,这是否与性能有任何可衡量的差异,我无法告诉。这是值得检查的。



正如@LURD正确地说, List 返回内部存储。而这可能不止于计数元素。具体来说,它有容量元素。所以,如果你使用它,你必须使用数组索引,元素 0 Count-1 访问元素。还要记住,对列表大小的修改可能涉及重新分配,因此内部存储可能会移动。您对列表的任何引用仅在下一次重新分配之前有效。



这些警告应该建议您,如果性能限制需要,您只要考虑使用 List 。即使如此,请谨慎使用。



在我的代码库中,我有一个替代方案 TList< T> ] 属性返回一个指向该元素的指针。容器仍然存储为动态数组,用于高效的内存布局。我喜欢这个选项到列表属性,因为我觉得它导致更清晰的代码。好的,你要看看我的列表类,它返回指针的元素。






这里是:

  type 
TReferenceList< T> = class(TBaseValueList< T>)
type
P = ^ T;
private
函数GetItem(Index:Integer):P;
public
属性项目[索引:整数]:P读取GetItem;默认;
public
// ....排除枚举器的帮助器类型
public
函数GetEnumerator:TEnumerator;
函数枚举器(Forwards:Boolean):TEnumeratorFactory;
函数ReverseEnumerator:TEnumeratorFactory;
函数IndexedEnumerator:TIndexedEnumeratorFactory;
结束

现在,需要一些解释。基本类别 TBaseValueList< T> 是我替代 TList< T> 。如果愿意,您可以替换 TList< T> 。我不是因为我的基类没有项目属性。那是因为我想要专门的课程来介绍它。我的其他专业是:

  type 
TValueList< T> = class(TBaseValueList< T>)
private
函数GetItem(Index:Integer):T;
程序SetItem(Index:Integer; const Value:T);
public
属性项目[索引:整数]:T读取GetItem写入SetItem;默认;
结束

实现我的 TBaseValueList< T> 很明显它非常类似于 TList< T> 。我不认为你真的需要看到任何实现。这是非常明显的。



作为一个简单的方法来获取元素的引用,你可以将列表像这样:

  type 
TMyList< T> = class(TList< T>)
public
type
P = ^ T;
private
function GetRef(Index:Integer):P;
public
property Ref [Index:Integer]:P读取GetRef;
结束

函数TMyList< T> .GetRef(Index:Integer):P;
begin
结果:= @List [Index];
结束

如果你想要一个比Delphi提供的更丰富的容器,你可能会关注Spring4D 。虽然我不知道他们有什么像我的容器返回引用。


I want to use a generic TList of records with a sub list in Delphi XE5:

type
  TMyRecord=record
    Value1: Real;
    SubList: TList<Integer>;
  end;

  TMyListOfRecords=TList<TMyRecord>;

var
  MyListOfRecords: TMyListOfRecords;

Assignments to the field of the records are not possible:

MyListOfRecords[0].Value1:=2.24; 

or

MyListOfRecords[0].SubList:=TList<Integer>.Create;

will result in "left side cannot be assigned to" error by the compiler.

See also: How to modify TList<record> value?

The following workaround works:

AMyRecord:=MyListOfRecords[0];
AMyRecord.Value1:=2.24;
AMyRecord.SubList:=TList<Integer>.Create;
AMyRecord.SubList.Add(33);
MyListOfRecords[0]:=AMyRecord;

Because of performance issues I would like to avoid to copy the data to the temporary AMyrecord. I would rather like to access the record fields and the sub list directly.

What is the best way to handle this?

解决方案

The list exposes its internal storage, which is a dynamic array, through the List property. So you can write:

MyListOfRecords.List[0].Value1 := 2.24; 

Whether this makes any measurable difference in performance in comparison to the alternative with value copies, I cannot tell. It would be worthwhile checking that.

As @LURD correctly says, List returns the internal storage. And this may have more than Count elements. Specifically it has Capacity elements. So, if you use it, you must access the elements using array indexing, over elements 0 to Count-1. Remember also that modifications to the size of the list may involve a re-allocation and so the internal storage may move. Any reference you take to List is only valid until the next re-allocation.

These warnings should suggest to you that you only consider using List if performance constraints demand so. And even then, use it sparingly.

In my codebase, I have an alternative to TList<T> whose Items[] property returns a pointer to the element. The container still stores as a dynamic array for efficient memory layout. I preferred this option to the List property because I felt it led to cleaner code.


OK, you asked to take a look at my list class that returns pointers to the elements. Here it is:

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;

Now, some explanation needed. The base class, TBaseValueList<T> is my alternative to TList<T>. You could substitute TList<T> if you wish. I don't because my base class does not have an Items property. That's because I want the specialized classes to introduce it. My other specialization is:

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;

The implementation of my TBaseValueList<T> is pretty obvious. It's very similar to TList<T>. I don't think you really need to see any of the implementation. It's all very obvious.

As a simple way to get a reference to an element, you could wrap List up like this:

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;

If you want a richer set of containers than is provided by Delphi, you might care to look at Spring4D. Although I'm not sure if they have anything like my container that returns references.

这篇关于具有子列表的通用TList记录?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆