2012-02-29 13 views
11

Rozważmy następujący przykład (używam Delphi XE):Delphi XE: Konstruktor klasy nie zostanie wywołana w klasie przy użyciu rodzajowych

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. 

Klasa constructur nigdy nie nazywa, a więc linia „klasa utworzona "nie jest drukowane. Jeśli jednak usuwam uogólnienie i zmienię TTestClass<T> na standardową klasę TTestClass, wszystko działa zgodnie z oczekiwaniami.

Czy brakuje mi czegoś z lekami generycznymi? Lub po prostu nie działa?

Wszelkie przemyślenia na ten temat zostaną zatrzymane!

Dzięki, --Stefan--

+0

[Dokumentacja] (http://docwiki.embarcadero.com/RADStudio/en/Methods#Class_Constructors) stwierdza: "Uwaga: Konstruktor klasy dla ogólnej klasy lub rekordu może być wykonywany wiele razy. Konstruktor klasy jest wykonywany w tym przypadku w zależności od liczby wyspecjalizowanych wersji typu ogólnego, na przykład konstruktor klasy specjalistycznej TList może wykonywać wiele razy w tej samej aplikacji. " Ale wygląda trochę jak błąd. –

+0

Tak. Ja też to czytam. Chyba że "wiele razy" zawiera zero razy, to naprawdę wygląda jak błąd. – Schafsmann

+0

Ogólna zasada: Nie próbuj tworzyć samodzielnej aplikacji .dpr. Zawsze dysponuj co najmniej jedną jednostką i trzymaj wszystko z plików DPR, których możesz uniknąć. –

Odpowiedz

9

Wygląda jak błąd kompilatora. Ten sam kod działa, jeśli przeniesiesz deklarację i implementację TTestClass do oddzielnej jednostki.

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 Osiągnąłem ten sam wniosek sam! –

+1

Świetnie, dzięki za rozwiązanie tego! Ja też dałbym +1, gdybym mógł. Właściwie to miałem swoją klasę w swojej jednostce, ale użyłem jej tylko w pliku .dpr. Tak więc odpowiedź na pytanie brzmi: Konstruktory klas klas ogólnych nie działają dla obiektów tworzonych w pliku .dpr. – Schafsmann

+0

i już zrobiłem :) – Schafsmann

11

Mogę potwierdzić, że jest to błąd. Jeśli jedyną instancją klasy jest plik .dpr, wówczas konstruktor klasy nie działa. Jeśli utworzysz inną jednostkę, tj. Oddzielny plik .pas i utworzysz stamtąd TTestClass<Integer>, wtedy twój konstruktor klas zostanie uruchomiony.

Przesłałem QC#103798.

+1

Nadal nie został naprawiony w XE5. Najgorsze jest to, że musisz zadeklarować lub utworzyć instancję zmiennej w oddzielnym pliku .pas. I musisz to zrobić dla każdego T używanego w twoim programie !! –

+2

Ciągle nie naprawiono w XE8 @LURD –

+0

@LURD EBMT wydaje się wymuszać na programistach trzymanie rąk z pliku DPR, o czym wspomniał WarrenP. – Fr0sT

Powiązane problemy