我需要存储一个临时的记录列表,并且认为TList会是一个很好的方法。然而,我不确定如何使用TList来做到这一点,我想知道这是不是最好的was,还有谁有任何关于如何做到这一点的例子?
发布于 2011-04-27 07:36:25
最简单的方法是创建您自己的TList后代。以下是一个快速示例控制台应用程序,用于演示:
program Project1;
{$APPTYPE CONSOLE}
uses
SysUtils, Classes;
type
PMyRec=^TMyRec;
TMyRec=record
Value: Integer;
AByte: Byte;
end;
TMyRecList=class(TList)
private
function Get(Index: Integer): PMyRec;
public
destructor Destroy; override;
function Add(Value: PMyRec): Integer;
property Items[Index: Integer]: PMyRec read Get; default;
end;
{ TMyRecList }
function TMyRecList.Add(Value: PMyRec): Integer;
begin
Result := inherited Add(Value);
end;
destructor TMyRecList.Destroy;
var
i: Integer;
begin
for i := 0 to Count - 1 do
FreeMem(Items[i]);
inherited;
end;
function TMyRecList.Get(Index: Integer): PMyRec;
begin
Result := PMyRec(inherited Get(Index));
end;
var
MyRecList: TMyRecList;
MyRec: PMyRec;
tmp: Integer;
begin
MyRecList := TMyRecList.Create;
for tmp := 0 to 9 do
begin
GetMem(MyRec, SizeOf(TMyRec));
MyRec.Value := tmp;
MyRec.AByte := Byte(tmp);
MyRecList.Add(MyRec);
end;
for tmp := 0 to MyRecList.Count - 1 do
Writeln('Value: ', MyRecList[tmp].Value, ' AByte: ', MyRecList[tmp].AByte);
WriteLn(' Press Enter to free the list');
ReadLn;
MyRecList.Free;
end.这消除了几件事:
正如Remy和Warren所说,这是一项更多的工作,因为当您添加新记录时,您必须分配内存。
发布于 2011-04-27 07:05:52
首先,如果你想把经典的TList和唱片结合起来,你需要:
将列表与记录相结合需要如此多的“指针和堆管理”工作,以至于这样的技术只能在专家的能力范围内。
除了您所要求的,仍然使用称为"TList“的东西的替代方案,包括使用具有记录类型的generics.collections样式的TList,这将具有TList的所有优点,但基本上需要您执行大量完整记录拷贝才能将数据放入其中。
最常用的Delphi方法是这样做的:
显示动态数组的代码示例:
TMyRec = record
///
end;
TMyRecArray = array of TMyRec;
procedure Demo;
var
myRecArray:TMyRecArray;
begin
SetLength(myRecArray,10);
end;现在,关于为什么TList不容易与记录类型一起使用的一些背景信息:
TList更适合与类类型一起使用,因为' TMyClass‘类型的变量,其中'type TMyClass=CLASS...end;’可以很容易地被“引用”为一个指针值,这就是TList所拥有的。
在Delphi中,类型为Record的变量是值类型,而类值是隐式引用的值。您可以将按引用的值视为隐形指针。您不必取消对它们的引用来获取它们的内容,但当您将其添加到TList中时,实际上只是添加了一个指向TList的指针,而不是创建副本或分配任何新内存。
雷米的答案从字面上告诉你如何做你想要的,我写我的答案只是因为我想警告你关于你正在询问的细节,并建议你也考虑其他选择。
发布于 2011-04-27 13:40:09
你可以看看我们的TDynArray wrapper。它是在一个开源单元中定义的,从Delphi 6一直到XE。
使用TDynArray,您可以使用TList-like属性和方法访问任何动态数组(如TIntegerDynArray = array of integer或TRecordDynArray = array of TMyRecord),例如Count, Add, Insert, Delete, Clear, IndexOf, Find, Sort和一些新方法,如LoadFromStream, SaveToStream, LoadFrom和SaveTo,它们允许快速二进制序列化任何动态数组,甚至包含字符串或记录-还可以使用CreateOrderedIndex方法根据动态数组内容创建单独的索引。如果愿意,还可以将数组内容序列化为JSON。还可以使用Slice, Reverse或Copy方法。
它将处理记录的动态数组,甚至记录中的记录,其中包含字符串或其他动态数组。
使用外部Count变量时,可以大大加快在引用的动态数组中添加元素的速度。
type
TPerson = packed record
sCountry: string;
sFullName: string;
sAddress: string;
sCity: string;
sEmployer: string;
end;
TPersons = array of TPerson;
var
MyPeople: TPersons;
(...)
procedure SavePeopleToStream(Stream: TMemoryStream);
var aPeople: TPerson;
aDynArray: TDynArray;
begin
aDynArray.Init(TypeInfo(TPersons),MyPeople);
aPeople.sCountry := 'France';
aPeople.sEmployer := 'Republique';
aDynArray.Add(aPeople);
aDynArray.SaveToStream(Stream);
end; // no try..finally Free needed here还有一个TDynArrayHashed类,它允许对动态数组内容进行内部散列。它非常快,能够散列任何类型的数据(有标准的字符串散列器,但您可以提供自己的散列器-甚至散列函数也可以自定义)。
请注意,TDynArray和TDynArrayHashed只是现有动态数组变量的包装器。因此,您可以根据需要初始化TDynArray包装器,以便更有效地访问任何本机dynamic数组。
https://stackoverflow.com/questions/5797368
复制相似问题