Saltar al contenido

Lista de registros de Delphi

Solución:

La forma más sencilla es crear su propio descendiente de TList. Aquí hay una aplicación de consola de muestra rápida para demostrar:

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.

Esto elimina un par de cosas:

  • Maneja liberar la memoria.
  • No tienes que encasillar todo para usarlo.

Como dijeron Remy y Warren, es un poco más de trabajo porque tienes que asignar la memoria cuando agregas nuevos registros.

Primero, si desea combinar un TList clásico con Records, deberá:

  1. Asigne sus registros en el montón, no en la pila. Utilice GetMem como lo hizo Remy.
  2. Tome la dirección del registro y agréguela a la TList.
  3. Cuando elimine un elemento de la lista y lo use, elimine la referencia:
  4. Recuerde liberar y limpiar después.

La combinación de listas con registros requiere tanto trabajo de “punteros y administración de montones” que tal técnica solo estaría dentro de las capacidades de un experto.

Alternativas a lo que ha solicitado que todavía usan algo llamado “TList”, incluyen el uso de un TList de estilo generics.collections, con tipos de registro, que tendría todos los beneficios de TList, pero que básicamente requeriría hacer mucho copias de registros para incorporar datos.

Las formas más idiomáticas de Delphi para hacer lo que pide son:

  1. use un TList o TObjectList con un tipo de clase en lugar de un registro. Por lo general, terminas subclasificando TList o TObjectList en este caso.

  2. Utilice una matriz dinámica de tipos de registro, pero tenga en cuenta que es más difícil ordenar un tipo de matriz y que expandir un tipo de matriz en tiempo de ejecución no es tan rápido como lo es con una TList.

  3. Use generics.Collections TList con sus clases. Esto le permite evitar subclasificar TList o TObjectList cada vez que desee utilizar una lista con una clase diferente.

Un ejemplo de código que muestra matrices dinámicas:

 TMyRec = record
    ///
 end;

 TMyRecArray = array of TMyRec;

 procedure Demo;
 var
    myRecArray:TMyRecArray;
 begin
    SetLength(myRecArray,10);
 end;

Ahora, para obtener información general sobre por qué TList no es fácil de usar con tipos de registro:

TList es más adecuado para su uso con tipos de clase, porque una variable de tipo ‘TMyClass’, donde ‘tipo TMyClass = class …. end;’ se puede “denominar” fácilmente como un valor de puntero, que es lo que contiene TList.

Las variables de tipo Registro son tipos de valor en Delphi, mientras que los valores de clase son implícitamente valores de referencia. Puede pensar en los valores de referencia como punteros sigilosos. No tiene que desreferenciarlos para acceder a su contenido, pero cuando lo agrega a una TList, en realidad solo está agregando un puntero a la TList, no haciendo una copia ni asignando ninguna memoria nueva.

La respuesta de Remy te muestra literalmente cómo hacerlo. exactamente lo que desea, y estoy escribiendo mi respuesta solo porque quiero advertirle sobre los detalles de lo que está preguntando y sugerirle que también considere alternativas.

Puede echar un vistazo a nuestro contenedor TDynArray. Se define en una unidad de código abierto, que funciona desde Delphi 6 hasta XE.

Con TDynArray, puede acceder a cualquier matriz dinámica (como TIntegerDynArray = array of integer o TRecordDynArray = array of TMyRecord) utilizando TList-como propiedades y métodos, p. ej. Count, Add, Insert, Delete, Clear, IndexOf, Find, Sort y algunos métodos nuevos como LoadFromStream, SaveToStream, LoadFrom y SaveTo que permiten la serialización binaria rápida de cualquier matriz dinámica, incluso que contenga cadenas o registros, una CreateOrderedIndex El método también está disponible para crear índices individuales de acuerdo con el contenido de la matriz dinámica. También puede serializar el contenido de la matriz en JSON, si lo desea. Slice, Reverse o Copy también hay métodos disponibles.

Manejará una matriz dinámica de registros, e incluso registros dentro de los registros, con cadenas u otras matrices dinámicas en su interior.

Cuando se utiliza un externo Count variable, puede acelerar mucho la adición de elementos en la matriz dinámica referida.

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

También hay una TDynArrayHashed class, que permiten el hash interno de un contenido de matriz dinámica. Es muy rápido y puede hacer hash de cualquier tipo de datos (existen hash estándar para cadenas, pero puede proporcionar los suyos propios, incluso la función hash se puede personalizar).

Tenga en cuenta que TDynArray y TDynArrayHashed son simplemente envoltorios alrededor de una variable de matriz dinámica existente. Por lo tanto, puede inicializar un TDynArray wrapper según sea necesario, para acceder de manera más eficiente a cualquier matriz dinámica nativa de Delphi.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *