2010-11-01 8 views
5

Delphi 1 16 bits (ouais il est vieux, mais il fonctionne bien)TStringList - comportement étrange

Quelques exemples de code:

procedure TForm1.Button1Click(Sender: TObject); 
var 
    SL: TStringList; 
begin 

    SL := TStringList.Create; 
    SL.Sorted := True; 
    SL.Duplicates := dupIgnore; 

    SL.AddObject('A', TObject(100)); 
    SL.AddObject('A', TObject(999)); 
    ShowMessage(IntToStr(LongInt(SL.Objects[0]))); {A} 

    SL.Free; 

end; 

J'utilise le champ objet pour stocker Entiers (un hack , oui mais ça fait le boulot). Quoi qu'il en soit, à la ligne A ci-dessus, je m'attendrais à ShowMessage à montrer 100, à la place, il montre 999 (même si dupIgnore est défini). Est-ce que j'ai râté quelque chose? Ou devrait-il fonctionner de cette façon (je m'attendais à ce que la liste de chaînes ignore le 999)?

Répondre

6

Juste testé dans Delphi 2009 - il montre 100 (et il devrait montrer 100 selon la documentation de Delphi 2009 sur les doublons et dupIgnore).

Probablement c'est Delphi 1 bug.


Mise à jour

@Sertac Akyuz: Oui, cela semble être vrai. Google shows que les anciennes versions Delphi avaient la mise en œuvre des méthodes suivantes TStringList.Add et TStringList.AddObject:

function TStringList.Add(const S: string): integer; 
begin 
    if not Sorted then 
    Result := FCount 
    else 
    if Find(S, Result) then 
     case Duplicates of 
     dupIgnore: Exit; 
     dupError: Error(SDuplicateString, 0); 
     end; 
    InsertItem(Result, S); 
end; 

function TStrings.AddObject(const S: string; AObject: TObject): Integer; 
begin 
    Result := Add(S); 
    PutObject(Result, AObject); 
end; 

L'implémentation actuelle (Delphi 2009) est:

function TStringList.Add(const S: string): Integer; 
begin 
    Result := AddObject(S, nil); 
end; 

function TStringList.AddObject(const S: string; AObject: TObject): Integer; 
begin 
    if not Sorted then 
    Result := FCount 
    else 
    if Find(S, Result) then 
     case Duplicates of 
     dupIgnore: Exit; 
     dupError: Error(@SDuplicateString, 0); 
     end; 
    InsertItem(Result, S, AObject); 
end; 

voir la différence. L'ancienne implémentation peut être vue comme un bug (fuite de mémoire, etc.) ou un comportement autorisé non documenté. Dans tous les cas, l'implémentation actuelle est libre du problème.

+0

[La documentation Delphi XE] (http://docwiki.embarcadero.com/VCL/fr/Classes.TStringList.AddObject) ne dit rien à ce sujet. Il dit seulement que les * chaînes * en double sont ignorées. Il ne dit rien sur ce qui arrive à l'objet lié à la chaîne en double. –

+0

@Rob Kennedy - dupIgnore bloque les tentatives d'ajout de chaînes dupliquées (avec ou sans objets) à la liste triée. L'index retourné n'a pas d'importance dans ce cas - la chaîne n'est pas ajoutée à la liste. – kludg

+0

Rob ne parle pas de la chaîne - elle n'est certainement pas ajoutée. Il parle de l'objet * lié à la chaîne de dupe. Le document ne dit pas ce qui arrive à l'objet. Avec les versions antérieures de Delphi, alors que la chaîne de dupe n'est pas ajoutée, l'objet lié à celle-ci remplace l'objet précédent. Cela devrait être considéré comme un choix de conception au lieu d'un bug, probablement un mauvais car ils l'ont changé (j'ai vu un post en 2004, donc le comportement a probablement changé après D7). –

3

Vous ne manquez rien. C'est exactement ce qui arrive. Commence par appeler Add, ce qui renvoie l'index du nouvel élément (ou existant) dans la liste. Ensuite, il appelle PutObject pour affecter la valeur de l'objet à cet index. Le comportement par rapport à la propriété Duplicates n'est pas spécifié dans la documentation.