【问题标题】:Generic method returning generic interface in Delphi 2010在 Delphi 2010 中返回泛型接口的泛型方法
【发布时间】:2011-04-04 05:07:14
【问题描述】:

鉴于下面的代码,这是实际代码的一个非常精简的版本,我收到以下错误:

[DCC 错误] Unit3.pas(31): E2010 不兼容类型:'IXList.FindAll.S>' 和 'TXList.FindAll.S>'

在 FindAll 函数中。

我真的不明白为什么,因为之前非常相似的功能没有问题。

谁能解释一下?
是我还是编译器的bug?

单元单元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.

感谢您的回答! 这似乎是一个编译器错误,具有可接受的解决方法。

接口声明为

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;

【问题讨论】:

    标签: delphi generics interface delphi-2010


    【解决方案1】:

    经过三处小修改(IInterface、带有“S: class”的 FindAll [感谢 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.
    

    【讨论】:

    • 很好,诀窍似乎是在类声明中显式命名 IInterface。谢谢。
    【解决方案2】:

    这绝对看起来像是编译器错误。他们说他们如何集中大量精力来改进下一个版本 Delphi XE 的泛型问题。当它发布时,应该在接下来的几周内,下载预览版,看看现在是否可以编译。如果没有,请尝试向 QC 提交错误报告。

    另外,FindAll&lt;S&gt; 可能应该被声明为function FindAll&lt;S: class&gt;: IXList&lt;S&gt;;。这并不能解决错误,但工作的编译器可能会给你一个错误。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-03-14
      • 2017-11-13
      • 2016-12-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多