2009-11-18 9 views
5

¿Hay alguna forma de determinar el tipo de variable pasada como argumento para un método? Considere la clase:Delphi: determinar el tipo real de un genérico?

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

con la implementación del método

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; 

donde TInt.Create() y TString.Create() tienen diferentes conjuntos de argumentos, sin embargo, ambos se heredan de TDataType.

Ahora, sé que el operador is no se puede usar así, pero ¿hay alguna alternativa legal que haga lo que estoy pidiendo aquí?

+4

Si lo primero que hace en su código genérico es escribir un código específico para cada valor genérico posible, entonces ya no está escribiendo código genérico. Este no es el lugar para usar los genéricos. –

+2

Gracias por la entrada Rob. Cuando publico preguntas en SO (y en otros lugares), suelo encontrar versiones simplificadas de mi código real. La extracción de la esencia del problema es, en mi experiencia, más útil que la presentación del código del código del mundo real, que generalmente es bastante más complejo. Por lo tanto, considere el código anterior como una ilustración de un problema mayor. Por cierto, me encantaría leer sobre una alternativa al código anterior. Por favor revisa mi pregunta de seguimiento: http://stackoverflow.com/questions/1761487/delphi-generics-and-is-operator-problem. ¡Estoy esperando cualquier entrada en esa publicación! :) – conciliator

Respuesta

5

No se puede utilizar el es operador aquí es un problema conocido, pero hay una solución bastante simple.

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

Además, dado que el tipo de un genérico es parte de la clase y es conocido en tiempo de compilación, es posible que sea mejor la reestructuración de su código. Haga dos clases genéricas diferentes, una de las cuales acepta un TInt como su parámetro <T>, y la otra acepta una TString. Coloque la funcionalidad específica de tipo en ese nivel, y haga que descienden de un antecesor común para la funcionalidad compartida.

+0

Gracias Mason! Sin embargo, aparece el error "E2089 typecast typecast". ¿Sabes por qué? Y puede que no haya estado claro en mi última publicación, pero TInt y TString descienden de TDataType, pero difieren en TInt y TString (en particular, sus constructores). Eso es lo que querías decir, ¿verdad? De todos modos, la restricción se coloca como "cerca" TInt y TString como sea posible para garantizar una funcionalidad óptima. – conciliator

+0

¿En qué línea está recibiendo el error? No tengo tu código para probar, pero escribí una prueba simple y el casting para TObject funciona bien para mí ... –

+0

En mi publicación original, estaba trabajando con un diseño más complejo, pero dí el ejemplo tal como se presentó arriba, porque captura el problema esencial que estoy teniendo. Entonces, cuando me preguntaron por la fuente completa, tuve que codificarla desde "cero". Se ve un poco diferente, pero todavía estoy teniendo el problema de la tipografía. ¿Debería publicarlo como una pregunta separada o como una respuesta a su publicación? – conciliator

4

Esta pregunta que hice hace algún tiempo

Conditional behaviour based on concrete type for generic class

podría ser de interés, especialmente si usted desea utilizar no sólo TObject descendientes, sino también los tipos primitivos en sus condicionales.

+1

+1 Me salvaste el día porque necesitaba la respuesta vinculada para habilitar las funciones de conversión genéricas para los tipos enumerados. –

Cuestiones relacionadas