2010-08-26 26 views
7

Với mã dưới đây, mà là một phiên bản rất tỉa xuống các mã thực tế, tôi nhận được lỗi sau:phương pháp Generic trở về giao diện chung trong Delphi 2010

[DCC Lỗi] Unit3.pas (31): E2010 loại không tương thích: 'IXList < Unit3.TXList <T> .FindAll.S >' và 'TXList < Unit3.TXList <T> .FindAll.S >'

Trong FindAll <S> chức năng.

Tôi thực sự không thể hiểu tại sao vì không có vấn đề với chức năng rất giống nhau trước đó.

Có ai có thể làm sáng tỏ không?
Có phải là tôi hoặc là một lỗi trong trình biên dịch?

đơn vị Unit3;

interface 
uses Generics.Collections; 

type 
    IXList<T> = interface 
    end; 

    TXList<T: class> = class(TList<T>, IXList<T>) 
    protected 
    FRefCount: Integer; 
    function QueryInterface(const IID: TGUID; out Obj): HResult; stdcall; 
    function _AddRef: Integer; stdcall; 
    function _Release: Integer; stdcall; 
    public 
    function Find: IXList<T>; 
    function FindAll<S>: IXList<S>; 
    end; 

implementation 
uses Windows; 

function TXList<T>.Find: IXList<T>; 
begin 
    Result := TXList<T>.Create; 
end; 

function TXList<T>.FindAll<S>: IXList<S>; 
begin 
    Result := TXList<S>.Create; // Error here 
end; 

function TXList<T>.QueryInterface(const IID: TGUID; out Obj): HResult; 
begin 
    Result := E_NoInterface; 
end; 

function TXList<T>._AddRef: Integer; 
begin 
    InterlockedIncrement(FRefCount); 
end; 

function TXList<T>._Release: Integer; 
begin 
    InterlockedDecrement(FRefCount); 
    if FRefCount = 0 then Self.Destroy; 
end; 

end. 

Cảm ơn câu trả lời! Có vẻ như lỗi trình biên dịch có giải pháp có thể chấp nhận được.

Với giao diện khai báo là

IXList<T: class> = interface 
    function GetEnumerator: TList<T>.TEnumerator; 
end; 

và FindAll thực hiện như

function TXList<T>.FindAll<S>: IXList<S>; 
var 
    lst: TXList<S>; 
    i: T; 
begin 
    lst := TXList<S>.Create; 
    for i in Self do 
    if i.InheritsFrom(S) then lst.Add(S(TObject(i))); 

    Result := IXList<S>(IUnknown(lst)); 
end; 

tôi đã nhận nó làm việc trong một ví dụ đơn giản.

Làm cái gì đó như:

var 
    l: TXList<TAClass>; 
    i: TASubclassOfTAClass; 
begin 
. 
. 
. 
for i in l.FindAll<TASubclassOfTAClass> do 
begin 
    // Do something with i 
end; 

Trả lời

5

Với ba sửa đổi nhỏ (IInterface, FindAll với "S: class" [Thanks Mason] và các typecasts trong FindAll) tôi đã biên dịch nó.

Full mã:

unit Unit16; 

interface 

uses 
    Generics.Collections; 

type 
    IXList<T> = interface 
    end; 

    TXList<T: class> = class(TList<T>, IInterface, IXList<T>) 
    protected 
    FRefCount: Integer; 
    function QueryInterface(const IID: TGUID; out Obj): HResult; stdcall; 
    function _AddRef: Integer; stdcall; 
    function _Release: Integer; stdcall; 
    public 
    function Find: IXList<T>; 
    function FindAll<S: class>: IXList<S>; 
    end; 

implementation 
uses Windows; 

function TXList<T>.Find: IXList<T>; 
begin 
    Result := TXList<T>.Create; 
end; 

function TXList<T>.FindAll<S>: IXList<S>; 
begin 
    Result := IXList<S>(IUnknown(TXList<S>.Create)); 
end; 

function TXList<T>.QueryInterface(const IID: TGUID; out Obj): HResult; 
begin 
    Result := E_NoInterface; 
end; 

function TXList<T>._AddRef: Integer; 
begin 
    InterlockedIncrement(FRefCount); 
end; 

function TXList<T>._Release: Integer; 
begin 
    InterlockedDecrement(FRefCount); 
    if FRefCount = 0 then Self.Destroy; 
end; 

end. 
+0

Nice, lừa dường như là để đặt tên một cách rõ ràng IInterface trong khai báo lớp. Cảm ơn. – PeterS

3

Đó chắc chắn trông giống như một lỗi biên dịch. Họ đang nói làm thế nào họ đã tập trung rất nhiều nỗ lực vào việc cải thiện các vấn đề Generics cho phiên bản tiếp theo, Delphi XE. Khi nó được phát hành, mà sẽ được trong vòng vài tuần tới, tải về xem trước và xem nếu đó sẽ biên dịch ngay bây giờ. Nếu không, hãy thử gửi báo cáo lỗi với QC.

Ngoài ra, FindAll<S> có lẽ phải được khai báo là function FindAll<S: class>: IXList<S>;. Điều đó không sửa lỗi, nhưng một trình biên dịch làm việc có thể sẽ cho bạn một lỗi về điều đó.

Các vấn đề liên quan