2010-11-01 33 views
5

Delphi 1 de 16 bits (sí es viejo, pero funciona bien)TStringList - comportamiento extraño

un código de ejemplo:

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; 

estoy usando el campo de objetos para almacenar enteros largos (un hack Sí, pero hace bien el trabajo). De todos modos, en la línea A anterior esperaría que ShowMessage muestre 100, en cambio muestra 999 (incluso si está configurado dupIgnore). ¿Me estoy perdiendo de algo? ¿O debería funcionar de esta manera (esperaba que el stringlist ignorara el 999)?

Respuesta

6

Acaba de probar en Delphi 2009 - muestra 100 (y debe mostrar 100 según la documentación de Delphi 2009 sobre Duplicados y DupIgnore).

Probablemente es Delphi 1 error.


Actualizado

@Sertac Akyuz: Sí, eso parece ser cierto. Google shows que las viejas versiones de Delphi tenían la siguiente implementación de métodos y 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; 

El (Delphi 2009) implementación actual es:

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; 

ver la diferencia. La implementación anterior puede verse como un error (pérdida de memoria, etc.) o un comportamiento permitido no documentado. En cualquier caso, la implementación actual está libre del problema.

+0

[La documentación de Delphi XE] (http://docwiki.embarcadero.com/VCL/en/Classes.TStringList.AddObject) no dice nada al respecto. Solo dice que las cadenas * duplicadas se ignoran. No dice nada sobre lo que sucede con el objeto vinculado a la cadena duplicada. –

+0

@Rob Kennedy - dupIgnore bloquea los intentos de agregar cadenas duplicadas (con o sin objetos) a la lista ordenada. El índice devuelto no importa en este caso: la cadena no se agrega a la lista. – kludg

+0

Rob no está hablando de la cadena, seguro que no se agrega. Él habla sobre el * objeto * atado a la cadena de engaño. Los documentos no dicen qué le sucede al objeto. Con las versiones anteriores de Delphi, aunque no se agrega la cadena dupe, el objeto vinculado reemplaza al objeto anterior. Debería considerarse una opción de diseño en lugar de un error, probablemente uno malo, ya que lo cambiaron (he visto una denuncia con fecha 2004, por lo que el comportamiento probablemente cambió después de D7). –

3

No le falta nada. Eso es exactamente lo que sucede.

AddObject comienza llamando al Add, que devuelve el índice del elemento nuevo (o existente) en la lista. Luego llama al PutObject para asignar el valor del objeto en ese índice. El comportamiento con respecto a la propiedad Duplicates no está especificado en la documentación.