2012-02-29 11 views
11

Considere el siguiente ejemplo (estoy usando Delphi XE):Delphi XE: constructor de la clase no se consiga llamar en una clase utilizando los genéricos

program Test; 

{$APPTYPE CONSOLE} 

type 
    TTestClass<T> = class 
    private 
    class constructor CreateClass(); 
    public 
    constructor Create(); 
    end; 

class constructor TTestClass<T>.CreateClass(); 
begin 
    // class constructor is not called. this line never gets executed! 
    Writeln('class created'); 
end; 

constructor TTestClass<T>.Create(); 
begin 
    // this line, of course, is printed 
    Writeln('instance created'); 
end; 

var 
    test: TTestClass<Integer>; 

begin 
    test := TTestClass<Integer>.Create(); 
    test.Free(); 
end. 

El constructur clase nunca es llamado y 'clase de ahí la línea creada 'no está impreso. Sin embargo, si elimino la generalización y hago TTestClass<T> en una clase estándar TTestClass, todo funciona como se esperaba.

¿Me estoy perdiendo algo con genéricos? O simplemente no funciona?

¡Cualquier idea sobre esto sería aprehendida!

Gracias, --Stefan--

+0

La [documentación] (http://docwiki.embarcadero.com/RADStudio/es/Methods#Class_Constructors) establece: "Nota: El constructor de clase para una clase o registro genérico puede ejecutarse varias veces. La cantidad exacta de veces el constructor de clase se ejecuta en este caso depende del número de versiones especializadas del tipo genérico. Por ejemplo, el constructor de clase para una clase especializada TList puede ejecutarse varias veces en la misma aplicación. " Pero se parece un poco a un error entonces. –

+0

Sí. Yo también leo eso. A menos que "varias veces" incluya cero veces, esto realmente parece un error. – Schafsmann

+0

Regla general: no intente hacer una aplicación .dpr independiente. Siempre tenga al menos una unidad y mantenga todo fuera de los archivos DPR que puede mantener fuera de él. –

Respuesta

9

se parece a un error del compilador. El mismo código funciona si mueve la declaración e implementación de TTestClass a una unidad separada.

unit TestClass; 

interface 
type 
    TTestClass<T> = class 
    private 
    class constructor CreateClass(); 
    public 
    constructor Create(); 
    end; 

var 
    test: TTestClass<Integer>; 

implementation 

class constructor TTestClass<T>.CreateClass(); 
begin 
    Writeln('class created'); 
end; 

constructor TTestClass<T>.Create(); 
begin 
    Writeln('instance created'); 
end; 

end. 
+1

+1 ¡He llegado exactamente a la misma conclusión! –

+1

Genial, gracias por resolver esto! También haría +1 si pudiera. En realidad, tenía mi clase en su propia unidad, pero solo la usé en el archivo .dpr. Entonces, la respuesta a la pregunta es: los constructores de clase de clases genéricas no se ejecutan para los objetos instanciados en el archivo .dpr. – Schafsmann

+0

y ya lo hice :) – Schafsmann

11

Puedo confirmar que este es un error. Si la única instanciación de la clase está en el archivo .dpr, entonces el constructor de la clase no se ejecuta. Si crea otra unidad, es decir, un archivo .pas separado, y crea una instancia de TTestClass<Integer> desde allí, se ejecutará su constructor de clase.

He enviado QC#103798.

+1

Aún no se ha solucionado en XE5. Lo peor es que debe declarar o crear una instancia de una variable en el archivo .pas separado. ¡Y tienes que hacer eso por cada T usada en tu programa! –

+2

Todavía no se ha solucionado en XE8 @LURD –

+0

@LURD EBMT parece forzar a los codificadores a mantener sus manos alejadas del archivo DPR como lo mencionó WarrenP. – Fr0sT

Cuestiones relacionadas