col*_*lin 31 delphi record tlist
我需要存储一个临时的记录列表,并认为这TList是一个很好的方法吗?但是我不确定如何用a做这个TList并且想知道这是否是最好的,并且如果有人有任何如何做到这一点的例子?
Ken*_*ite 27
最简单的方法是创建自己的后代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.
Run Code Online (Sandbox Code Playgroud)
这消除了以下几点:
正如雷米和沃伦所说,这是一个更多的工作,因为你必须在添加新记录时分配内存.
War*_* P 18
首先,如果您想将经典TList与Records结合使用,您需要:
将列表与记录结合起来需要大量的"指针和堆管理"工作,这种技术只能在专家的能力范围内.
您所要求的替代品仍然使用称为"TList"的东西,包括使用generics.collections样式的TList,使用记录类型,这将具有TList的所有好处,但需要您基本上完成很多 - 记录副本以获取数据.
最常用的Delphi方法可以做到你要求的:
使用带有类类型的TList或TObjectList而不是记录.通常,在这种情况下,您最终会继承TList或TObjectList.
使用动态的记录类型数组,但请注意,对类型进行排序更加困难,并且在运行时扩展数组类型并不像使用TList那样快速.
使用generics.Collections TList与您的类.这使您可以在每次要使用具有不同类的列表时避免继承TList或TObjectList.
显示动态数组的代码示例:
TMyRec = record
///
end;
TMyRecArray = array of TMyRec;
procedure Demo;
var
myRecArray:TMyRecArray;
begin
SetLength(myRecArray,10);
end;
Run Code Online (Sandbox Code Playgroud)
现在有一些关于为什么TList不易于使用Record类型的背景信息:
TList更适合与Class类型一起使用,因为'TMyClass'类型的变量,其中'type TMyClass = class .... end;' 可以很容易地"引用"为指针值,这是TList所持有的.
Record类型的变量是Delphi中的value-Types,而类值是隐式的引用值.您可以将by-reference值视为隐形指针.您不必取消引用它们来获取它们的内容,但是当您将它添加到TList时,您实际上只是添加指向TList的指针,而不是复制或分配任何新内存.
雷米的答案从字面上向你展示了如何完全按照自己的意愿行事,而我正在写答案只是因为我想警告你所要求的细节,并建议你考虑其他选择.
Arn*_*hez 11
你可以看看我们的TDynArray包装器.它在开源单元中定义,从Delphi 6到XE.
有了TDynArray,您可以访问任何动态数组(如TIntegerDynArray = array of integer或TRecordDynArray = array of TMyRecord使用)TList般的属性和方法,比如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
Run Code Online (Sandbox Code Playgroud)
还有一个TDynArrayHashed类,它允许动态数组内容的内部散列.它非常快,能够散列任何类型的数据(有字符串的标准哈希,但你可以提供自己的 - 甚至可以自定义哈希函数).
需要注意的是TDynArray与TDynArrayHashed 只是围绕现有动态数组变量包装.因此,您可以TDynArray根据需要初始化包装器,以便更有效地访问任何本机Delphi动态数组.
您可以使用 TList 来实现此目的,例如:
type
pRec = ^sRec;
sRec = record
Value: Integer;
...
end;
var
List: TList;
Rec: pRec;
I: Integer;
begin
List := TList.Create;
try
for I := 1 to 5 do begin
GetMem(Rec);
try
Rec^.Value := ...;
...
List.Add(Rec);
except
FreeMem(Rec);
raise;
end;
end;
...
for I := 0 to List.Count-1 do
begin
Rec := pRec(List[I]);
...
end;
...
for I := 0 to List.Count-1 do
FreeMem(pRec(List[I]));
List.Clear;
finally
List.Free;
end;
end;
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
56121 次 |
| 最近记录: |