2008-11-12 6 views
2

J'ai une TObjectList avec OwnsObjects = true. Il contient pas mal d'objets. Maintenant, je veux supprimer l'objet à l'index Idx de cette liste, sans le libérer.extrait un objet d'une TObjectList

La méthode Extract est-elle la seule option?

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

Toutes les autres méthodes semblent libérer l'objet. Je cherche quelque chose d'un peu plus efficace, qui ne fait pas une recherche linéaire à chaque fois, puisque je connais déjà l'index de l'objet. Quelque chose comme une surcharge ...

ExtractedObject := TheList.Extract(Idx);

... qui n'existe pas.

Répondre

8

Pourquoi ne pas simplement définir OwnsObjects sur false, supprimer, puis redéfinir à true?

+0

trop facile ;-) Merci –

0

Je n'utilise pas Delphi/C++ Builder il y a quelque temps, mais pour autant que je puisse me rappeler c'est le seul moyen. Ma suggestion est d'utiliser un TList à la place, et de supprimer manuellement les objets si nécessaire.

1

Si vous examinez le code à supprimer, c'est la méthode notify qui provoque la libération.

Cela devrait fonctionner:

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; 
1

C'est là des aides de classe peut être utile

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; 

Vous pouvez maintenant utiliser:

MyObjList.ExtractByIndex(MyIndex); 
+0

Malheureusement, cela fera toujours une recherche linéaire dans la fonction d'extraction d'origine, même si j'ai déjà passé l'index de l'objet à la nouvelle fonction d'extraction. Mais je suppose que combiner cela avec OwnsObjects = False/True devrait faire l'affaire. –

1

Le helperClass proposé (par Gamecat) sera aboutir à la même recherche que Thomas aimerait se débarrasser de.

Si vous regardez la source, vous pouvez voir ce que fait vraiment Extract(), et ensuite utiliser la même approche.

Je proposerai quelque chose comme tis:

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

Cela vous donnera l'objet, comme l'extrait() fait, puis supprimer de la liste, sans recherches. Maintenant, vous pouvez mettre cela dans une méthode où, une classe d'assistance ou une sous-classe ou où vous voulez.

+0

Malheureusement, cela ne fonctionne pas non plus puisque l'affectation de NIL à un élément le libère automatiquement. –

+0

Oups. J'ai complètement négligé celui-là, mais TList vous donne un accès direct à la liste liée, à travers la propriété publique List: PPoinerList. Changer la liste [idx]: = nil to list.List^[i]: = nil; et la solution devrait être saine. – Vegar

0

ya un problème avec:

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

Il faut du temps pour la création et l'affectation, mais pas pour la recherche dans la liste. L'efficacité dépend de la taille de l'objet -v- la taille de la liste.

+0

cette approche nécessite que l'objet descende de TPersistent et implémente correctement la méthode Assign –