Given the code below, wich is a very trimmed 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>'
In the FindAll<S> function.
I can't really see why since there is no problem with the previous very similar function.
Can anyone shed some light on it?
Is it me or is it a bug in the compiler?
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 the answers! It seems like a compiler bug with an acceptable workaround available.
With the interface declared as
IXList<T: class> = interface
function GetEnumerator: TList<T>.TEnumerator;
end;
and findall 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 got it working in 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;
With three minor modification (IInterface, FindAll with "S: class" [Thanks Mason] and the typecasts in FindAll) I got it compiling.
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.
That definitely looks like a compiler error. They're saying how they've focused a lot of effort into improving Generics issues for the next version, Delphi XE. When it gets released, which should be within the next couple weeks, download the preview and see if that will compile now. If not, try filing a bug report with QC.
Also, FindAll<S>
should probably be declared as function FindAll<S: class>: IXList<S>;
. That doesn't fix the error, but a working compiler would probably give you an error on that.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With