Почему при освобождении TObjectList также удаляются элементы управления?

Я использую TObjectList для обработки определенного списка меток. Но когда я делаю рекомендуемый .Free в Try Final, он также удаляет элементы управления из списка.

Простой пример с 3 метками:

Procedure GetHeaderLabels(var aList:TObjectList<TLabel>);
begin
  aList.Add(Form1.lblHeaderCars);
  aList.Add(Form1.lblHeaderBrands);
  aList.Add(Form1.lblHeaderModels);
end;

procedure TForm1.Button1Click(Sender: TObject);
var vHeaderLabelsList:TObjectList<TLabel>;
begin
  vHeaderLabelsList:=TObjectList<TLabel>.Create;
  try
     GetHeaderLabels(vHeaderLabelsList);
      {... process Header Labels }
  finally
    vHeaderLabelsList.Free;
  end;
end;

В этом случае, когда я выполняю этот код, я получаю отсутствующие элементы управления метками - они удаляются из формы, а в отладке я вижу, что элементы управления равны нулю.

Разве я не должен .Free TObjectList? Как я могу освободить TObjectlist и при этом сохранить элементы управления?


person Matej mtj    schedule 03.09.2016    source источник


Ответы (2)


TObjectList имеет свойство OwnsObjects, которое по умолчанию равно True. Если вы не измените это в какой-то момент, прежде чем освободить его, он освободит содержащиеся в нем объекты. Если вы этого не хотите, установите OwnsObjects на False.

vHeaderLabelsList := TObjectList<TLabel>.Create(False);

Если вам не нужны объекты, принадлежащие (очищенные) TObjectList, вместо этого лучше просто использовать TList:

vHeaderLabelsList := TList<TLabel>.Create;
person Ken White    schedule 03.09.2016
comment
Нет, мне нужен только их список, чтобы не копировать один и тот же код для каждой этикетки. - person Matej mtj; 03.09.2016

Вы наткнулись на разницу между TObjectList и TList<TObject>.

Объект TObjectList «владеет» объектами в списке, что означает, что по умолчанию он уничтожит все содержащиеся в нем объекты при удалении объекта из списка или при уничтожении самого списка.
Если вы не хотите для этого либо используйте TList<TObject>, либо установите OwnsObjects в false перед добавлением элементов в список.
Обычно это делается в конструкторе, но вы также можете установить его позже.

Все это четко указано в документации.

Если запись принадлежит, когда объект записи удаляется из списка, объект записи освобождается.

Свойство OwnsObjects получает или задает право собственности на объект.

Вы действительно должны проверить: http://docwiki.embarcadero.com, когда происходит что-то неожиданное, прежде чем спешить с SO: - ).

person Johan    schedule 03.09.2016
comment
Обратите внимание, что существует также неуниверсальная версия TObjectList, которая также имеет свойство OwnsObjects. И TStringList также имеет свойство OwnsObjects для записей в его свойстве Objects[]. - person Remy Lebeau; 03.09.2016
comment
Я прочитал документацию, но только для того, чтобы увидеть, что ot должен выполнять эту работу. Очевидно, мне следует читать дальше. - person Matej mtj; 03.09.2016
comment
Однако стоит отметить, что документация для TObjectList‹T› идентифицирует эту возможность, но не говорит, включена ли она по умолчанию, только то, что параметр ctor включает или выключает ее. Как написано, документация не дает оснований полагать, что это поведение по умолчанию (если только вы специально и отдельно не проверите ссылку на конструктор Create и не обнаружите, что указанный параметр имеет значение TRUE, если не указано). Напротив, в документации Contnrs.TObjectList ясно, что это поведение по умолчанию. RTFM дает сбой, когда FM находится в состоянии FU. :) - person Deltics; 05.09.2016