2013-02-27 61 views
7

xem xét chiết mã sau:Delphi: OleVariant và 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; 

này thất bại trong việc biên dịch với các thông báo lỗi như đã nêu ở trên. Làm thế nào tôi có thể gọi hàm Work từ lớp chung của tôi?

+2

Tại sao oh lý do tại sao là câu hỏi tốt này nhận được phiếu gần? Các cử tri có nhìn vào những gì họ bỏ phiếu không? –

+0

Không phải lo lắng, chúng tôi luôn có thể mở lại :-) – Johan

+3

@Johan Chúng ta không cần phải làm như vậy. Những hàng đợi xem xét tại SO chỉ là ngu ngốc. –

Trả lời

8

Mã của bạn không biên dịch được vì trình biên dịch không thể đảm bảo thời gian biên dịch của lớp chung chung mà có thể chuyển đổi thành tất cả có thể tưởng tượng được T.

Khi đối mặt với

intf.Work(param); 

trong phương pháp chung trình biên dịch cần phải biết làm thế nào để chuyển đổi param-OleVariant. Và nó không thể làm như vậy. Đây là một trong những hạn chế của Generics so với các mẫu.


Các giải pháp dễ dàng nhất cho bạn là để làm việc chuyển đổi trong thời gian chạy với sự giúp đỡ từ TValue từ các đơn vị Rtti.

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

Và đây là một chương trình thử nghiệm mẫu để chứng minh rằng TValue hiện công việc:

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. 

Output

 
2.4 
hello 
-666