2010-08-26 3 views
7

Учитывая приведенный ниже код, которым очень урезана версия фактического кода, я получаю следующее сообщение об ошибке:Общий метод, возвращающий общий интерфейс в Delphi 2010

[DCC Error] Unit3.pas (31): E2010 Несовместимые типы: 'IXList < < Unit3.TXList Т > > .FindAll.S' и 'TXList < < Unit3.TXList Т > > .FindAll.S'

В > функции FindAll < S.

Я не могу понять, почему, поскольку нет проблем с предыдущей очень подобной функцией.

Может ли кто-нибудь пролить свет на него?
Это я или это ошибка в компиляторе?

единица измерения 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. 

Спасибо за ответы! Кажется, ошибка компилятора с приемлемым обходным решением.

С интерфейсом объявлен

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

и FindAll реализованы как

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; 

Я получил это работает в простом примере.

Делать что-то вроде:

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

ответ

5

С тремя незначительными модификациями (IInterface, FindAll с «S: class» [Спасибо, Mason] и приемы в FindAll) Я получил его компиляцию.

Полный код:

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

Ницца, трюк, казалось бы явно назвать IInterface в объявлении класса. Спасибо. – PeterS

3

Это определенно выглядит как ошибка компилятора. Они говорят, что они сосредоточили много усилий на улучшении проблем Generics для следующей версии Delphi XE. Когда он будет выпущен, который должен быть в течение следующих нескольких недель, загрузите предварительный просмотр и посмотрите, будет ли он теперь компилироваться. Если нет, попробуйте подать отчет об ошибке с помощью QC.

Кроме того, FindAll<S> следует, вероятно, объявить как function FindAll<S: class>: IXList<S>;. Это не исправляет ошибку, но рабочий компилятор, вероятно, даст вам ошибку.

Смежные вопросы