Как освободить общий TList‹TMyRecord› с общими подсписками в TMyRecord

В Delphi 10 Berlin под Windows у меня есть следующий вопрос об освобождении общих списков:

У меня есть следующая структура записи/списка:

type
  TMyRecord=record
    Value1: Real;
    SubList1: TList<Integer>;
    SubList2: TList<Real>;
  end;

  TMyListOfRecords=TList<TMyRecord>;

Я хочу освободить структуру с помощью следующего кода:

var
  i: Integer;
  AMyListOfRecords: TMyListOfRecords;
begin
  //other code

  //free AMyListOfRecords and all its content
  for i:=0 to AMyListOfRecords.Count-1 do
  begin
    AMyListOfRecords[i].SubList1.Free;
    AMyListOfRecords[i].SubList2.Free;
  end;
  AMyListOfRecords.Free;
end;

Кажется, это работает. Но мне интересно, есть ли более простое или элегантное решение?


person user3384674    schedule 31.05.2016    source источник
comment
Если вы можете использовать DeHL, вы можете просто использовать IList‹›, и он будет автоматически управляться, как и любые другие интерфейсные объекты.   -  person Z.B.    schedule 31.05.2016
comment
В противном случае вы можете просто реализовать свою собственную оболочку над IList‹T› над TList‹T› и сделать это TInterfacedObject.   -  person Z.B.    schedule 31.05.2016
comment
Ваш код кажется мне хорошим   -  person David Heffernan    schedule 31.05.2016
comment
Я рекомендую использовать общие коллекции с интерфейсом Spring4Ds - DeHL просто мертв.   -  person Stefan Glienke    schedule 31.05.2016
comment
@StefanGlienke спасибо за упоминание .. Я просто не помнил, что, поскольку мы еще не используем Spring4D, я не смог вспомнить, где он был :)   -  person Z.B.    schedule 01.06.2016


Ответы (2)


Вы можете определить интерфейсный список для таких подэлементов, как:

type
  TMyRecord=record
    Value1: Real;
    SubList1: IList<Integer>;
    SubList2: IList<Real>;
  end;

  TMyListOfRecords=TList<TMyRecord>;

Где IList вроде:

type
  IList<T> = interface
    function Add(const AValue: T): Integer;
    function Remove(AValue: T): Integer;
  end;

где вы реализуете это следующим образом:

  TIntfList<T> = class(TInterfacedObject, IList<T>)
  private
    FList: TList<T>;
    function Add(const AValue: T): Integer;
    function Remove(AValue: T): Integer;

    constructor Create;
    destructor Destroy; override;
  end;

{ TIntfList<T> }

function TIntfList<T>.Add(const AValue: T): Integer;
begin
  Result := FList.Add(AValue);
end;

constructor TIntfList<T>.Create;
begin
  FList := TList<T>.Create;
end;

destructor TIntfList<T>.Destroy;
begin
  FList.Free;
  inherited;
end;

function TIntfList<T>.Remove(AValue: T): Integer;
begin
  Result := FList.Remove(AValue);
end;

После этого вы можете назначить поля вашей записи с помощью TIntfList.Create, и они будут автоматически освобождены вместе с вашими записями.

person Z.B.    schedule 31.05.2016

Вы можете преобразовать тип записи в класс — накладные расходы незначительны, поскольку запись уже содержит подобъекты. Освободите подобъекты в этом деструкторе класса и используйте

 TMyListOfClasses = TObjectList<TMyClass>;

с OwnsObjects = True

В этом случае все, что вам нужно, это

AMyListOfClasses.Free;
person MBo    schedule 31.05.2016
comment
Поддерживает ли он отдельный список принадлежащих ему объектов для уничтожения или использует для этого RTTI? - person Michael; 02.06.2016
comment
@Michael TObjectList - это просто список объектов, он уничтожает все его элементы (если OwnsObjects), нет необходимости в отдельном списке или RTTI - person MBo; 02.06.2016
comment
Да я старая школа. Я предпочитаю использовать деструктор, потому что иногда у вас нет собственной опции, и я забываю. - person Michael; 20.06.2016