2013-02-27 15 views
7

Si consideri il seguente estratto di codice:Delphi: OleVariant e 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; 

Questo non riesce a compilare con il messaggio di errore come sopra indicato. Come posso chiamare la funzione Work dalla mia classe generica?

+2

Perché oh perché è questa bella domanda avvicinarsi voti? Gli elettori guardano anche a cosa stanno votando? –

+0

Non ti preoccupare, possiamo sempre riaprire :-) – Johan

+3

@Johan Non avremmo dovuto. Queste code di revisione su SO sono semplicemente stupide. –

risposta

8

Il tuo codice non riesce a compilare perché il compilatore non può garantire al momento della compilazione della classe generica che esiste una possibile conversione a tutti i possibili T.

Di fronte a

intf.Work(param); 

nel metodo generico il compilatore ha bisogno di sapere come convertire param-OleVariant. E non può farlo. Questo è uno dei limiti dei generici rispetto ai modelli.


La soluzione più semplice per voi è quello di fare la conversione in fase di esecuzione con l'aiuto di TValue dall'unità Rtti.

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

Ed ecco un programma di test di esempio per dimostrare che TValue fa il lavoro:

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. 

uscita

 
2.4 
hello 
-666