2010-08-26 15 views
7

Dato il codice qui sotto, che è una versione molto assettato giù del codice vero e proprio, ottengo il seguente errore:metodo generico ritorno un'interfaccia generica in Delphi 2010

[DCC Error] Unit3.pas (31): E2010 tipi incompatibili: 'IXList < Unit3.TXList <T> .FindAll.S >' e 'TXList < Unit3.TXList <T> .FindAll.S >'

Nella funzione FindAll <S>.

Non riesco a capire perché, poiché non esiste alcun problema con la funzione molto simile precedente.

Qualcuno può far luce su di esso?
Sono io o si tratta di un bug nel compilatore?

unità Unità 3;

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. 

Grazie per le risposte! Sembra un bug del compilatore con una soluzione accettabile disponibile.

Con l'interfaccia dichiarato come

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

e FindAll implementati come

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; 

ho ottenuto che funziona in un semplice esempio.

fare qualcosa di simile:

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

risposta

5

Con tre modifiche minori (IInterface, FindAll con "S: class" [Grazie Mason] e i typecasts in FindAll) ho ottenuto la compilazione.

codice completo:

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

Nizza, il trucco sembrava essere quello di nominare esplicitamente IInterface nella dichiarazione della classe. Grazie. – PeterS

3

Questo sembra decisamente come un errore di compilazione. Stanno dicendo che hanno concentrato un grande sforzo per migliorare i problemi di Generics per la prossima versione, Delphi XE. Quando viene rilasciato, che dovrebbe essere entro le prossime due settimane, scarica l'anteprima e verifica se questo verrà compilato ora. In caso contrario, prova a presentare una segnalazione di errore con QC.

Inoltre, FindAll<S> dovrebbe essere dichiarato come function FindAll<S: class>: IXList<S>;. Questo non risolve l'errore, ma un compilatore funzionante probabilmente ti darebbe un errore.

Problemi correlati