Извлечь объект из TObjectList
У меня есть TObjectList с OwnsObjects = true. Он содержит довольно много объектов. Теперь я хочу удалить объект с индексом Idx из этого списка, не освобождая его.
Является ли метод Extract единственным вариантом?
ExtractedObject := TheList.Extract(TheList[Idx]);
Все остальные методы, кажется, освобождают объект. Я ищу что-то более эффективное, которое не выполняет линейный поиск каждый раз, так как я уже знаю индекс объекта. Что-то вроде перегрузки...
ExtractedObject := TheList.Extract(Idx);
... которого не существует
6 ответов
Почему бы просто не установить для OwnsObjects значение false, выполнить удаление, а затем снова установить для него значение true?
Здесь помощники класса могут быть полезны
TObjectListHelper = class helper for TObjectList
function ExtractByIndex(const AIndex: Integer): TObject;
end;
function TObjectListHelper.ExtractByIndex(const AIndex: Integer): TObject;
begin
Result := Items[AIndex];
if Result<>nil then
Extract(Result);
end;
Теперь вы можете использовать:
MyObjList.ExtractByIndex(MyIndex);
Предложенный вспомогательный класс (от Gamecat) приведет к тому же поиску, от которого Томас хотел бы избавиться.
Если вы посмотрите на источник, вы можете увидеть, что действительно делает Extract(), и затем использовать тот же подход.
Я предложу что-то вроде этого:
obj := list[idx];
list.list^[idx] := nil; //<- changed from list[idx] := nil;
list.delete(idx);
Это даст вам объект, как это делает Extract(), а затем удалит его из списка без поиска. Теперь вы можете поместить это в какой-нибудь метод helperclass или subclass, или когда захотите.
Если вы посмотрите на код для удаления, это метод notify, который вызывает освобождение.
Это должно работать:
TMyObjectList = Class(TObjectList)
private
fNotify: Boolean;
{ Private declarations }
procedure EnableNotification;
procedure DisableNotification;
protected
procedure Notify(Ptr: Pointer; Action: TListNotification); override;
public
constructor Create(AOwnsObjects: Boolean);overload;
constructor Create; overload;
function Extract(const idx : Integer) : TObject;
end;
constructor TMyObjectList.Create(AOwnsObjects: Boolean);
begin
inherited Create(AOwnsObjects);
fNotify := True;
end;
constructor TMyObjectList.Create;
begin
inherited Create;
fNotify := True;
end;
procedure TMyObjectList.DisableNotification;
begin
fnotify := False;
end;
procedure TMyObjectList.EnableNotification;
begin
fNotify := True;
end;
function TMyObjectList.Extract(const idx: Integer) : TObject;
begin
Result := Items[idx];
DisableNotification;
try
Delete(idx);
finally
EnableNotification;
end;
end;
procedure TMyObjectList.Notify(Ptr: Pointer; Action: TListNotification);
begin
if fNotify then
inherited;
end;
Что-то не так с:
ExtractedObject: = TExtractedObject.Create;
ExtractedObject.Assign (Thelist [Idx]);
TheList.Delete (IDX);
Существует время, необходимое для создания и назначения, но не для поиска в списке. Эффективность зависит от размера объекта -v- размера списка.
Некоторое время назад я не использую Delphi/C++Builder, но насколько я могу судить, это единственный способ. Я предлагаю вместо этого использовать TList и вручную удалять объекты, когда это необходимо.