Generic method that returns a generic interface in Delphi 2010

Given the code below, which is a very stripped-down version of the actual code, I get the following error:

[DCC Error] Unit3.pas (31): E2010 Incompatible types: 'IXList <Unit3.TXList <T> .FindAll.S>' and 'TXList <Unit3.TXList <T> .FindAll.S>'

The FindAll <S> function.

I can’t understand why, since there is no problem with the previous very similar function.

Can anyone shed light on him?
Is it me or is it a compiler error?

unit 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. 

Thanks for answers! This seems like a compiler error with an acceptable workaround.

With an interface declared as

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

and findall are implemented as

 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; 

I tried working with a simple example.

Doing something like:

 var l: TXList<TAClass>; i: TASubclassOfTAClass; begin . . . for i in l.FindAll<TASubclassOfTAClass> do begin // Do something with i end; 
+7
generics interface delphi delphi-2010
source share
2 answers

With three minor modifications (IInterface, FindAll with "S: class" [Thanks to Mason] and type tricks in FindAll), I got it compiled.

Full code:

 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. 
+5
source share

This definitely looks like a compiler error. They say they have focused a lot on improving Generics issues for the next version of Delphi XE. When it is released, which is due in the next few weeks, download the preview and see if it will now compile. If not, try reporting the error using QC.

In addition, FindAll<S> should probably be declared as function FindAll<S: class>: IXList<S>; . This does not fix the error, but a working compiler will probably give you an error.

+3
source share

All Articles