首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Delphi TList of records

Delphi TList of records
EN

Stack Overflow用户
提问于 2011-04-27 06:46:48
回答 8查看 66.6K关注 0票数 35

我需要存储一个临时的记录列表,并且认为TList会是一个很好的方法。然而,我不确定如何使用TList来做到这一点,我想知道这是不是最好的was,还有谁有任何关于如何做到这一点的例子?

EN

回答 8

Stack Overflow用户

回答已采纳

发布于 2011-04-27 07:36:25

最简单的方法是创建您自己的TList后代。以下是一个快速示例控制台应用程序,用于演示:

代码语言:javascript
复制
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所说,这是一项更多的工作,因为当您添加新记录时,您必须分配内存。

票数 27
EN

Stack Overflow用户

发布于 2011-04-27 07:05:52

首先,如果你想把经典的TList和唱片结合起来,你需要:

  1. 将记录分配到堆上,而不是堆栈上。像雷米一样使用GetMem。
  2. 获取记录的地址并将其添加到TList。
  3. 当从列表中删除项目并使用它时,请取消对它的引用:
  4. 记住释放并清理,之后。

将列表与记录相结合需要如此多的“指针和堆管理”工作,以至于这样的技术只能在专家的能力范围内。

除了您所要求的,仍然使用称为"TList“的东西的替代方案,包括使用具有记录类型的generics.collections样式的TList,这将具有TList的所有优点,但基本上需要您执行大量完整记录拷贝才能将数据放入其中。

最常用的Delphi方法是这样做的:

  1. 使用带有类类型的TList或TObjectList,而不是使用记录。通常,在这种情况下,您最终将子类化为TList或TObjectList。
  2. 使用记录类型的动态数组,但请注意,数组类型更难排序,并且在运行时扩展数组类型不如使用TList快。
  3. 对您的类使用generics.Collections TList。这使您可以避免每次要使用具有不同类的列表时都对TList或TObjectList进行子类化。

显示动态数组的代码示例:

代码语言:javascript
复制
 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的指针,而不是创建副本或分配任何新内存。

雷米的答案从字面上告诉你如何做你想要的,我写我的答案只是因为我想警告你关于你正在询问的细节,并建议你也考虑其他选择。

票数 19
EN

Stack Overflow用户

发布于 2011-04-27 13:40:09

你可以看看我们的TDynArray wrapper。它是在一个开源单元中定义的,从Delphi 6一直到XE。

使用TDynArray,您可以使用TList-like属性和方法访问任何动态数组(如TIntegerDynArray = array of integerTRecordDynArray = array of TMyRecord),例如Count, Add, Insert, Delete, Clear, IndexOf, Find, Sort和一些新方法,如LoadFromStream, SaveToStream, LoadFromSaveTo,它们允许快速二进制序列化任何动态数组,甚至包含字符串或记录-还可以使用CreateOrderedIndex方法根据动态数组内容创建单独的索引。如果愿意,还可以将数组内容序列化为JSON。还可以使用Slice, ReverseCopy方法。

它将处理记录的动态数组,甚至记录中的记录,其中包含字符串或其他动态数组。

使用外部Count变量时,可以大大加快在引用的动态数组中添加元素的速度。

代码语言:javascript
复制
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类,它允许对动态数组内容进行内部散列。它非常快,能够散列任何类型的数据(有标准的字符串散列器,但您可以提供自己的散列器-甚至散列函数也可以自定义)。

请注意,TDynArrayTDynArrayHashed只是现有动态数组变量的包装器。因此,您可以根据需要初始化TDynArray包装器,以便更有效地访问任何本机dynamic数组。

票数 11
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/5797368

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档