извлечь объект из TObjectList - PullRequest
2 голосов
/ 12 ноября 2008

У меня есть TObjectList с OwnsObjects = true. Он содержит довольно много объектов. Теперь я хочу удалить объект с индексом Idx из этого списка, не освобождая его.

Является ли метод извлечения единственным вариантом?

ExtractedObject := TheList.Extract(TheList[Idx]);

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

ExtractedObject := TheList.Extract(Idx);

... которого не существует.

Ответы [ 6 ]

8 голосов
/ 12 ноября 2008

Почему бы просто не установить для OwnsObjects значение false, выполнить удаление, а затем снова установить для него значение true?

1 голос
/ 13 ноября 2008

Предлагаемый вспомогательный класс (от Gamecat) приведет к тому же поиску, от которого Томас хотел бы избавиться.

Если вы посмотрите на источник, вы сможете увидеть, что на самом деле делает Extract (), и затем использовать тот же подход.

Я предложу что-то вроде этого:

obj := list[idx];
list.list^[idx] := nil;  //<- changed from list[idx] := nil;
list.delete(idx);

Это даст вам объект, как это делает Extract (), а затем удалит его из списка без поиска. Теперь вы можете поместить это в метод some, вспомогательный класс или подкласс, или когда захотите.

1 голос
/ 12 ноября 2008

Здесь могут быть полезны помощники класса

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);
1 голос
/ 12 ноября 2008

Если вы посмотрите на код для удаления, это метод уведомления, который вызывает освобождение.

Это должно работать:

  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;
0 голосов
/ 13 ноября 2008

Что-то не так с:

ExtractedObject: = TExtractedObject.Create;
ExtractedObject.Assign (Thelist [Idx]);
TheList.Delete (IDX);

Есть время, необходимое для создания и назначения, но не для поиска в списке. Эффективность зависит от размера объекта -v- размера списка.

0 голосов
/ 12 ноября 2008

Некоторое время назад я не использую Delphi / C ++ Builder, но, насколько я могу судить, это единственный способ. Я предлагаю вместо этого использовать TList и вручную удалять объекты, когда это необходимо.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...