Delphi T 记录列表
我需要存储临时记录列表,并且认为 TList
是实现此目的的好方法?但是我不确定如何使用 TList
执行此操作,并且想知道这是否是最好的,以及是否有人有任何如何执行此操作的示例?
I need to store a temporary list of records and was thinking that a TList
would be a good way to do this? However I am unsure how to do this with a TList
and was wondering if this is the best was and also if anyone has any examples of how to do this?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(8)
最简单的方法是创建您自己的
TList
后代。下面是一个用于演示的快速示例控制台应用程序:这消除了一些事情:
正如雷米和沃伦所说,这需要更多的工作,因为在添加新记录时必须分配内存。
The easiest way is to create your own descendant of
TList
. Here's a quick sample console app to demonstrate:This eliminates a couple of things:
As Remy and Warren both said, it's a little more work because you have to allocate the memory when you add new records.
首先,如果您想将经典 TList 与记录结合起来,您将需要:
将列表与记录结合起来需要大量的“指针和堆管理”工作,以至于这种技术只有专家才能做到。
您所要求的替代方案仍然使用称为“TList”的东西,包括使用 generics.collections 样式的 TList 和 Record 类型,这将具有 TList 的所有优点,但需要您基本上做很多完整的事情 -记录副本以将数据放入其中。
完成您所要求的操作的最惯用的 Delphi 方法是:
使用带有类类型的 TList 或 TObjectList 而不是记录。在这种情况下,通常您最终会子类化 TList 或 TObjectList。
在您的类中使用 generics.Collections TList。这可以让您避免每次想要使用具有不同类的列表时对 TList 或 TObjectList 进行子类化。
显示动态数组的代码示例:
现在了解一些关于为什么 TList 不容易与 Record 类型一起使用的背景信息:
TList 更适合与 Class 类型一起使用,因为类型为 'TMyClass' 的变量,其中 'type TMyClass = class 。 ... 结尾;'可以很容易地“引用”为指针值,这就是 TList 所保存的内容。
Record 类型的变量是 Delphi 中的值类型,而类值是隐式的引用值。您可以将引用值视为隐形指针。您不必取消引用它们即可获取其内容,但是当您将其添加到 TList 时,实际上只是添加了指向 TList 的指针,而不是进行复制或分配任何新内存。
雷米的答案从字面上向您展示了如何准确做您想做的事情,我写下我的答案只是因为我想警告您您所问问题的细节,并建议您考虑也有替代品。
First, if you want to combine a classic TList with Records, you will need to:
Combining Lists with Records requires so much "pointers-and-heap-management" work that such a technique would be only within the capabilities of an expert.
Alternatives to what you have asked for that still use something called "TList", include using a generics.collections style TList, with Record types, which would have all the benefits of TList, but would require you to basically do a lot of entire-record-copies to get data into it.
The most idiomatic Delphi ways to do what you ask are to either:
use a TList or TObjectList with a Class Types instead of a record. Usually you end up subclassing either TList or TObjectList in this case.
Use a dynamic Array of Record Types, but be aware that it's harder to sort an Array type, and that expanding an array type at runtime isn't as speedy as it is with a TList.
Use generics.Collections TList with your classes. This lets you avoid subclassing TList or TObjectList each time you want to use a list with a different class.
A code sample showing Dynamic arrays:
Now for some background information on why TList is not easy to use with Record types:
TList is better suited for use with Class types, because a variable of type 'TMyClass', where 'type TMyClass = class .... end;' can be easily "referred to" as a pointer value, which is what TList holds.
Variables of type Record are value-Types in Delphi, whereas class values are implicitly by-reference values. You can think of by-reference values as stealth-pointers. You don't have to dereference them to get at their contents, but when you add it to a TList, you're actually just adding a pointer to the TList, not making a copy or allocating any new memory.
The answer by Remy shows you literally you how to do exactly what you want, and I am writing my answer only because I want to warn you about the details of what you are asking, and suggest that you consider alternatives too.
您可以查看我们的 TDynArray 包装器。它在开源单元中定义,适用于 Delphi 6 到 XE。
借助
TDynArray
,您可以使用TList< 访问任何动态数组(例如
TIntegerDynArray = 整数数组
或TRecordDynArray = TMyRecord 数组
) /code> 类似的属性和方法,例如Count、Add、Insert、Delete、Clear、IndexOf、Find、Sort
以及一些新方法,例如LoadFromStream、SaveToStream、LoadFrom
和SaveTo
允许对任何动态数组进行快速二进制序列化,甚至包含字符串或记录 - 还可以使用CreateOrderedIndex
方法根据动态数组内容创建单独的索引。如果您愿意,还可以将数组内容序列化为 JSON。还可以使用Slice、Reverse
或Copy
方法。它将处理记录的动态数组,甚至记录中的记录,其中包含字符串或其他动态数组。
使用外部
Count
变量时,您可以大大加快在引用的动态数组中添加元素的速度。还有一个 TDynArrayHashed 类,它允许对动态数组内容进行内部哈希处理。它非常快并且能够对任何类型的数据进行散列(有用于字符串的标准散列器,但您可以提供自己的 - 甚至散列函数也可以自定义)。
请注意,
TDynArray
和TDynArrayHashed
只是现有动态数组变量的包装器。因此,您可以根据需要初始化TDynArray
包装器,以更有效地访问任何本机 Delphi 动态数组。You can take a look at our TDynArray wrapper. It's defined in an Open Source unit, working from Delphi 6 up to XE.
With
TDynArray
, you can access any dynamic array (likeTIntegerDynArray = array of integer
orTRecordDynArray = array of TMyRecord
) usingTList
-like properties and methods, e.g.Count, Add, Insert, Delete, Clear, IndexOf, Find, Sort
and some new methods likeLoadFromStream, SaveToStream, LoadFrom
andSaveTo
which allow fast binary serialization of any dynamic array, even containing strings or records - aCreateOrderedIndex
method is also available to create individual index according to the dynamic array content. You can also serialize the array content into JSON, if you wish.Slice, Reverse
orCopy
methods are also available.It will handle a dynamic array of records, and even records within records, with strings or other dynamic arrays inside.
When using an external
Count
variable, you can speed up a lot the adding of elements in the referred dynamic array.There is also a
TDynArrayHashed
class, which allow internal hashing of a dynamic array content. It's very fast and able to hash any kind of data (there are standard hashers for strings, but you can supply your own - even the hash function can be customized).Note that
TDynArray
andTDynArrayHashed
are just wrappers around an existing dynamic array variable. You can therefore initialize aTDynArray
wrapper on need, to access more efficiently any native Delphi dynamic array.您可以使用 TList 来实现此目的,例如:
You can use TList for that, eg:
使用 System.Generics.Collections 中的 Generiс TList。
如果您需要通过引用访问通用 TList 中的记录并且不复制记录:
使用List.List - 直接访问TList数组。
现在您可以访问 Tlist 数组中的记录而无需复制它。
Use Generiс TList from System.Generics.Collections.
If you need to access to a record in generic TList by-reference and do not copy record:
use List.List - direct access to the array of TList.
Now you can access to record inside Tlist array without copying it.
如果使用不存在泛型的旧版本 Delphi,请考虑从 TList 继承并覆盖 Notify 方法。添加项目时,分配内存,复制添加的指针内存内容并覆盖列表中的内容。删除时,只需释放内存即可。
用法:
If using an older version of Delphi where generics isn't present, consider inheriting from TList and override Notify method. When adding an item, alloc memory, copy added pointer memory content and override content in list. When removing, just free memory.
Usage:
这完全取决于您要存储的数据类型。
您可以考虑使用
TCollection
和TCollectionItem
。这是来自工作单元的(编辑)代码,其中我使用
TCollection
从文件夹中读取报告定义列表。每个报告都包含一种模板和一条 SQL 语句,必须与文件名一起存储。由于它是经过编辑的,并且使用了我自己的一些单元(TedlFolderRtns 将文件读取到内部列表中,仅举一个例子),因此该示例足够简单且有用。通过少数替换全部,您可以适应您的任何需求。
在帮助中查找TCollection,你可以用它做很多事情。它可以让您的代码处理很好地分组在类似类的结构中。
用作:
It all depends on the type of data you want to store.
You might consider using
TCollection
andTCollectionItem
.Here is (edited) code from a working unit, in which I used
TCollection
to read a list of report definitions from a folder. Each report consisted of a sort of template and an SQL statement which had to be stored together with a file name.Since it is edited, and uses some of my own units (TedlFolderRtns reads files into an internal list, to name but one), the example is simple enough to be useful. With a few replace all, you can adapt to whatever your need.
Look up TCollection in the help, you can do a lot with it. And it keeps your code handling nicely grouped together in a class-like structure.
Use as :
我们刚刚在通用记录列表中遇到了类似的问题。希望以下伪代码有所帮助。
We've just run into a similar issue here with a generic list of records. Hope the following psuedo code helps.