2013-02-27 21 views
7

Betrachten Sie den folgenden Code-Ausschnitt:Delphi: OleVariant und Generics

type 
    MyIntf = interface 
    procedure Work(param: OleVariant); 
    end; 

    MyClass<T> = class 
    procedure MyWork(param: T); 
    end; 

var 
    intf: MyIntf; 

procedure MyClass<T>.MyWork(param: T); 
begin 
    //compiler error: E2010 Incompatible types: 'OleVariant' and 'T' 
    intf.Work(param); 
end; 

Dies schlägt mit der Fehlermeldung zu kompilieren, wie oben angegeben. Wie kann ich die Funktion Work von meiner generischen Klasse aufrufen?

+2

Warum oh warum ist diese feine Frage immer enger Stimmen? Sehen die Wähler überhaupt nach, worüber sie abstimmen? –

+0

Keine Sorge, wir können immer wieder öffnen :-) – Johan

+3

@Johan Wir sollten nicht müssen. Diese Review-Warteschlangen bei SO sind einfach dumm. –

Antwort

8

Ihr Code kann nicht kompiliert werden, da der Compiler zur Kompilierzeit der generischen Klasse nicht garantieren kann, dass eine Konvertierung in alle denkbaren T möglich ist.

Wenn mit

intf.Work(param); 

in der generischen Methode konfrontiert der Compiler muss wissen, wie param-OleVariant zu konvertieren. Und es kann nicht so sein. Dies ist eine der Einschränkungen von Generika im Vergleich zu Vorlagen.


Die einfachste Lösung für Sie ist es, die Umwandlung zur Laufzeit mit Hilfe von TValue von der Rtti Einheit zu tun.

procedure MyClass<T>.MyWork(param: T); 
begin 
    intf.Work(TValue.From<T>(param).AsVariant); 
end; 

Und hier ist ein Beispieltestprogramm zu zeigen, dass TValue den Job:

program SO15113162; 
{$APPTYPE CONSOLE} 

uses 
    Rtti; 

procedure Work(param: OleVariant); 
begin 
    Writeln(param); 
end; 

type 
    MyClass<T> = class 
    class procedure MyWork(param: T); 
    end; 

class procedure MyClass<T>.MyWork(param: T); 
begin 
    Work(TValue.From<T>(param).AsVariant); 
end; 

begin 
    MyClass<Double>.MyWork(2.4); 
    MyClass<string>.MyWork('hello'); 
    MyClass<Integer>.MyWork(-666); 
    Readln; 
end. 

Ausgabe

 
2.4 
hello 
-666