La risposta di Alex è la soluzione corretta al problema. E fa anche bene a tornare dalla funzione non appena la risposta è nota.
Mi piacerebbe ampliare la risposta con qualche spiegazione in più. In particolare vorrei rispondere alla domanda che hai posto nei commenti alla risposta di Alex:
Come una parte ... perché l'originale non funziona? T è derivata da X.
Il codice problema è qui:
function XList<T>.Find(Id: Integer): T;
var
t: X;
begin
for t in Self do
if t.Id = Id then
Result := t;
end;
Il modo di pensare farmaci generici, è immaginare quello che il codice sembra quando si crea un'istanza il tipo e la fornitura di un tipo concreto parametro. In questo caso, sostituiamo T
con Y
. Quindi il codice è simile:
function XList_Y.Find(Id: Integer): Y;
var
t: X;
begin
for t in Self do
if t.Id = Id then
Result := t;
end;
ora avete un problema alla linea che assegna a Result
:
Result := t;
Beh, Result
è di tipo Y
, ma t
è di tipo X
. La relazione tra X
e Y
è che Y
deriva da X
. Quindi un'istanza di Y
è un X
. Ma un'istanza di X
non è un Y
. E così il compito non è valido.
Come ha giustamente sottolineato Alex, è necessario dichiarare la variabile di loop di tipo T
. Personalmente mi sento di scrivere il codice in questo modo:
function XList<T>.Find(Id: Integer): T;
begin
for Result in Self do
if Result.Id = Id then
exit;
Result := nil;
// or perhaps you wish to raise an exception if the item cannot be found
end;
Questo affronta anche il problema che la ricerca di routine lascia il suo valore di ritorno inizializzato nel caso in cui l'articolo non viene trovato.Questo è un problema che il compilatore avrebbe avvertito circa una volta ottenuto il codice fino alla compilazione effettiva. Spero che tu abiliti gli avvertimenti del compilatore e gestirli quando appaiono!
fonte
2013-10-22 12:02:23
Grandi cose @AlexSC. Originariamente avevo 'var t: T'. Mi ero dimenticato di insensibilità al caso. La roba dei miei generici di C# è arrivata lì! – Rob
Per inciso ... perché il lavoro originale non funziona? T è derivato da X. – Rob
@Rob: mi dispiace, non ho una risposta per questo. Per me il compilatore ha individuato il messaggio di errore nell'ultima riga dell'unità, ciò che mi suggerisce che ha qualcosa a che fare con l'istanza di tipo generico. Sembra che il compilatore sia molto severo riguardo alla corrispondenza dei tipi quando si tratta di generici. – AlexSC