2009-11-18 15 views
5

Esiste un modo per determinare il tipo di una variabile passata come argomento a un metodo? Si consideri la classe:Delphi: determina il tipo effettivo di un generico?

TSomeClass = class 
    procedure AddToList<T: TDataType; U: TListClass<T>>(Element: T; List: U); 
end; 

con l'implementazione del metodo

procedure TSomeClass.AddToList<T, U>(Element: T; List: U); 
begin 
    if Element is TInt then 
    List.AddElement(TInt.Create(XXX)) 
    else if Element is TString then 
    List.AddElement(TString.Create(YYY)); 
end; 

dove TInt.Create() e TString.Create() hanno diverse serie di argomentazioni, eppure, entrambi ereditano da TDataType.

Ora, so che il is -operator non può essere utilizzato in questo modo, ma esiste un'alternativa legale che fa ciò che sto chiedendo qui?

+4

Se la prima cosa che fai nel tuo codice generico è scrivere un codice specifico per ogni possibile valore generico, non stai più scrivendo codice generico. Questo non è il posto dove usare i farmaci generici. –

+2

Grazie per l'input Rob. Quando pubblico domande a SO (e in altri luoghi), di solito mi vengono in mente versioni del mio vero codice. Estrarre l'essenza del problema è, secondo la mia esperienza, più utile della presentazione di codice di codice del mondo reale che di solito è molto più complesso. Quindi, per favore considera il codice sopra l'illustrazione di un problema più grande. A proposito: mi piacerebbe leggere su un'alternativa al codice di cui sopra. Si prega di controllare la mia domanda di follow-up: http://stackoverflow.com/questions/1761487/delphi-generics-and-is-operator-problem. Non vedo l'ora di ricevere commenti su quel post! :) – conciliator

risposta

5

Non essere in grado di utilizzare l'operatore è l'operatore qui è un problema noto, ma c'è una soluzione abbastanza semplice.

if TObject(Element) is TInt then 
    List.AddElement(TInt.Create(XXX)) 

Inoltre, dato che il tipo di un generico è parte della classe ed è noto al momento della compilazione, si potrebbe essere meglio ristrutturazione codice. Crea due diverse classi generiche, una delle quali accetta una TInt come parametro <T> e l'altra accetta TString. Metti le funzionalità specifiche del tipo in esse a quel livello e falle discendere da un antenato comune per la funzionalità condivisa.

+0

Grazie Mason! Tuttavia, ricevo un errore "typecast E2089 non valido". Sai perché? E forse non sono stato chiaro nel mio ultimo post, ma TInt e TString entrambi discendono da TDataType, ma differiscono a livello di TInt e TString (in particolare i loro costruttori). Questo è quello che intendevi, giusto? In ogni caso, il vincolo viene inserito il più vicino possibile a TInt e TString per garantire una funzionalità ottimale. – conciliator

+0

In quale riga viene visualizzato l'errore? Non ho il tuo codice per testare, ma ho scritto un semplice test e il casting per TObject funziona bene per me ... –

+0

Nel mio post originale, stavo lavorando con un design più complesso, ma ho dato l'esempio presentato sopra, perché cattura il problema essenziale che sto avendo. Quindi, quando ho chiesto l'intera fonte, ho dovuto codificarlo da "zero". Sembra un po 'diverso, ma sto ancora avendo il problema di typecast. Devo postarlo come una domanda separata o come risposta al tuo post? – conciliator

4

Questa domanda ho chiesto qualche tempo fa

Conditional behaviour based on concrete type for generic class

potrebbe essere di vostro interesse, soprattutto se si desidera utilizzare non solo TObject discendenti, ma anche i tipi primitivi nelle vostre condizionali.

+1

+1 Hai salvato il mio giorno perché avevo bisogno della risposta collegata per abilitare le funzioni di conversione generiche per i tipi enumerati. –

Problemi correlati