Pregunta

Tengo una TObjectList con OwnsObjects = true. Contiene bastantes objetos. Ahora quiero eliminar el objeto en el índice Idx de esa lista, sin liberarlo.

¿Es el método de extracción la única opción?

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

Todos los demás métodos parecen liberar el objeto. Estoy buscando algo un poco más eficiente, que no haga una búsqueda lineal cada vez, ya que ya conozco el índice del objeto. Algo así como un sobrecargado ...

ExtractedObject: = TheList.Extract (Idx);

... que no existe.

¿Fue útil?

Solución

¿Por qué no solo establece OwnsObjects en falso, realiza su eliminación y luego lo establece en verdadero nuevamente?

Otros consejos

Si observa el código para eliminar, es el método de notificación el que causa la liberación.

Esto debería funcionar:

  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;

Aquí es donde los ayudantes de clase pueden ser útiles

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;

Ahora puede usar:

MyObjList.ExtractByIndex(MyIndex);

La clase de ayuda propuesta (por Gamecat) dará como resultado la misma búsqueda de la que Thomas quisiera deshacerse.

Si echas un vistazo a la fuente, puedes ver qué hace realmente Extract () y luego usar el mismo enfoque.

Sugeriré algo como esto:

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

Esto le dará el objeto, como lo hace Extract (), y luego lo eliminará de la lista, sin ninguna búsqueda. Ahora puede poner esto en un método en algún lugar, una clase auxiliar o subclase o donde quiera.

No uso Delphi / C ++ Builder hace algún tiempo, pero hasta donde puedo recordar esa es la única forma. Mi sugerencia es utilizar un TList en su lugar y eliminar manualmente los objetos cuando sea necesario.

Algo malo con:

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

Se necesita tiempo para crear y asignar, pero no para buscar en la lista. La eficiencia depende del tamaño del objeto -v- el tamaño de la lista.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top