2010-11-01 32 views
5

Delphi 1 a 16 bit (sì è vecchio, ma funziona bene)TStringList - strano comportamento

Alcuni codice di esempio:

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; 

Sto utilizzando il campo oggetto per memorizzare longints (un hack sì, ma ha fatto il lavoro). Ad ogni modo, alla riga A sopra mi aspetto che ShowMessage mostri 100, invece mostri 999 (anche se dupIgnore è impostato). Mi sto perdendo qualcosa qui? O dovrebbe funzionare in questo modo (mi aspettavo che la lista di stringhe ignorasse la 999)?

risposta

6

Appena testato in Delphi 2009 - mostra 100 (e dovrebbe mostrare 100 secondo la documentazione di Delphi 2009 su Duplicati e dupIgnore).

Probabilmente si tratta di Delphi 1 bug.


Aggiornato

@Sertac Akyuz: Sì, che sembra essere vero. Google shows che le vecchie versioni di Delphi hanno avuto la seguente applicazione di metodi e TStringList.Add 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'attuale (Delphi 2009) implementazione è:

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; 

vedere la differenza. La vecchia implementazione può essere vista come un bug (perdita di memoria, ecc.) O un comportamento consentito non documentato. In ogni caso l'implementazione attuale è esente dal problema.

+0

[La documentazione di Delphi XE] (http://docwiki.embarcadero.com/VCL/en/Classes.TStringList.AddObject) non dice nulla al riguardo. Dice solo che le stringhe * duplicate sono ignorate. Non dice nulla su ciò che accade all'oggetto legato alla stringa duplicata. –

+0

@Rob Kennedy - dupIgnore blocca i tentativi di aggiungere stringhe duplicate (con o senza oggetti) all'elenco ordinato. L'indice restituito non ha importanza in questo caso: la stringa non viene aggiunta all'elenco. – kludg

+0

Rob non sta parlando della stringa, ma sicuramente non viene aggiunta. Parla di * oggetto * legato alla stringa del dupe. I documenti non dicono cosa succede all'oggetto. Con le versioni precedenti di Delphi, mentre la stringa dupe non viene aggiunta, l'oggetto associato sostituisce l'oggetto precedente. Dovrebbe essere considerata una scelta progettuale invece di un bug, probabilmente una cattiva scelta dal momento della loro modifica (ho visto un post che si lamentava del 2004, quindi il comportamento probabilmente è cambiato dopo D7). –

3

Non ti manca nulla. Questo è esattamente quello che succede.

AddObject inizia chiamando Add, che restituisce l'indice del nuovo (o esistente) elemento nell'elenco. Quindi chiama PutObject per assegnare il valore dell'oggetto a quell'indice. Il comportamento rispetto alla proprietà Duplicates non è specificato nella documentazione.