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<
The easiest way is to create your own descendant of TList
. Here's a quick sample console app to demonstrate:
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.
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.
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.
TOwnedList = class(TList)
private
FPtrSize: integer;
protected
procedure Notify(Ptr: Pointer; Action: TListNotification); override;
public
constructor Create(const APtrSize: integer);
end;
constructor TOwnedList.Create(const APtrSize: integer);
begin
inherited Create();
FPtrSize := APtrSize;
end;
procedure TOwnedList.Notify(Ptr: Pointer; Action: TListNotification);
var
LPtr: Pointer;
begin
inherited;
if (Action = lnAdded) then begin
GetMem(LPtr, FPtrSize);
CopyMemory(LPtr, Ptr, FPtrSize); //May use another copy kind
List^[IndexOf(Ptr)] := LPtr;
end else if (Action = lnDeleted) then begin
FreeMem(Ptr, FPtrSize);
end;
end;
Usage:
...
LList := TOwnedList.Create(SizeOf(*YOUR RECORD TYPE HERE*));
LList.Add(*YOU RECORD POINTER HERE*);
...