加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

在Delphi中实现列表枚举器OfType

发布时间:2020-12-15 10:17:53 所属栏目:大数据 来源:网络整理
导读:我使用Delphi XE实现枚举器,允许按类型过滤列表的元素。我已经快速组装了一个测试单元如下: unit uTestList;interfaceuses Generics.Collections;type TListItemBase = class(TObject) end; { TListItemBase } TListItemChild1 = class(TListItemBase) end
我使用Delphi XE实现枚举器,允许按类型过滤列表的元素。我已经快速组装了一个测试单元如下:
unit uTestList;

interface

uses Generics.Collections;

type
  TListItemBase = class(TObject)
  end; { TListItemBase }

  TListItemChild1 = class(TListItemBase)
  end;

  TListItemChild2 = class(TListItemBase)
  end;

  TTestList<T : TListItemBase> = class;

  TOfTypeEnumerator<T,TFilter> = class(TInterfacedObject,IEnumerator<TFilter>)
  private
    FTestList : TList<T>;
    FIndex : Integer;
  protected
    constructor Create(Owner : TList<T>); overload;

    function GetCurrent : TFilter;
    function MoveNext : Boolean;
    procedure Reset;

    function IEnumerator<TFilter>.GetCurrent = GetCurrent;
    function IEnumerator<TFilter>.MoveNext = MoveNext;
    procedure IEnumerator<TFilter>.Reset = Reset;
  end;

  TOfTypeEnumeratorFactory<T,IEnumerable)
  private
    FTestList : TList<T>;
  public
    constructor Create(Owner : TList<T>); overload;
    function GetEnumerator : TOfTypeEnumerator<T,TFilter>;
  end;

  TTestList<T : TListItemBase> = class(TList<T>)
  public
    function OfType<TFilter : TListItemBase>() : IEnumerable;
  end; { TTestList }


implementation

{ TOfTypeEnumerator<T,TFilter> }

constructor TOfTypeEnumerator<T,TFilter>.Create(Owner: TList<T>);
begin
  inherited;
  FTestList := Owner;
  FIndex := -1;
end;

function TOfTypeEnumerator<T,TFilter>.GetCurrent: TFilter;
begin
  Result := TFilter(FTestList[FIndex]);
end;

function TOfTypeEnumerator<T,TFilter>.MoveNext: Boolean;
begin
  Inc(FIndex);
  while ((FIndex < FTestList.Count)
         and (not FTestList[FIndex].InheritsFrom(TFilter))) do
  begin
    Inc(FIndex);
  end; { while }
end;

{ TOfTypeEnumeratorFactory<T,TFilter> }

constructor TOfTypeEnumeratorFactory<T,TFilter>.Create(Owner: TList<T>);
begin
  inherited;
  FTestList := Owner;
end;

function TOfTypeEnumeratorFactory<T,TFilter>.GetEnumerator: TOfTypeEnumerator<T,TFilter>;
begin
  Result := TOfTypeEnumerator<T,TFilter>.Create(FTestList);
end;

{ TTestList<T> }

function TTestList<T>.OfType<TFilter>: IEnumerable;
begin
  Result := TOfTypeEnumeratorFactory<T,TFilter>.Create(self);
end;

end.

编译本机失败,可怕的F2084内部错误:D7837。我当然可以做到这一点没有一个枚举者,但我宁愿有一个可以使代码一致。当我尝试在Spring4D之上实现这一点时,我遇到了一个类似的编译器问题,但是我想在这里提出一个简单的vanilla Delphi问题。

有没有人有实际编译的替代实现?

谢谢。

解决方法

您不想使用IEnumerator< T>从System.pas,相信我。那个东西带来了很多麻烦,因为它继承自IEnumerator,因此具有不同结果的GetCurrent方法(用于IEnumerator的TObject和用于IEnumerator&T的T)。

更好地定义您自己的IEnumerator< T:

IEnumerator<T> = interface
  function GetCurrent: T;
  function MoveNext: Boolean;
  procedure Reset;
  property Current: T read GetCurrent;
end;

与IEnumerable相同。我会说定义你自己的IEnumerable< T:

IEnumerable<T> = interface
  function GetEnumerator: IEnumerator<T>;
end;

如果您在TOFTypeEnumerator< T,TFilter>您可以删除导致ICE的方法解析条款。

当您这样做时,您将看到其他编译器错误E2008,E2089等。

>在你的构造函数中继承的调用尝试在你的祖先类中调用不存在相同签名的构造函数。所以改为继承创建。
>不要使用IEnumerable,但使用IEnumerable< TFilter>因为这是你想要的枚举者
>不要使用仅允许对象使用的方法和转换,或者在T和TFilter上指定类约束
> MoveNext需要一个结果

这是编译单元。做了一个快速测试,似乎工作:

unit uTestList;

interface

uses
  Generics.Collections;

type
  IEnumerator<T> = interface
    function GetCurrent: T;
    function MoveNext: Boolean;
    property Current: T read GetCurrent;
  end;

  IEnumerable<T> = interface
    function GetEnumerator: IEnumerator<T>;
  end;

  TOfTypeEnumerator<T: class; TFilter: class> = class(TInterfacedObject,IEnumerator<TFilter>)
  private
    FTestList: TList<T>;
    FIndex: Integer;
  protected
    constructor Create(Owner: TList<T>); overload;

    function GetCurrent: TFilter;
    function MoveNext: Boolean;
  end;

  TOfTypeEnumeratorFactory<T: class; TFilter: class> = class(TInterfacedObject,IEnumerable<TFilter>)
  private
    FTestList: TList<T>;
  public
    constructor Create(Owner: TList<T>); overload;
    function GetEnumerator: IEnumerator<TFilter>;
  end;

  TTestList<T: class> = class(TList<T>)
  public
    function OfType<TFilter: class>: IEnumerable<TFilter>;
  end;

implementation

{ TOfTypeEnumerator<T,TFilter>.Create(Owner: TList<T>);
begin
  inherited Create;
  FTestList := Owner;
  FIndex := -1;
end;

function TOfTypeEnumerator<T,TFilter>.GetCurrent: TFilter;
begin
  Result := TFilter(TObject(FTestList[FIndex]));
end;

function TOfTypeEnumerator<T,TFilter>.MoveNext: Boolean;
begin
  repeat
    Inc(FIndex);
  until (FIndex >= FTestList.Count) or FTestList[FIndex].InheritsFrom(TFilter);
  Result := FIndex < FTestList.Count;
end;

{ TOfTypeEnumeratorFactory<T,TFilter>.Create(Owner: TList<T>);
begin
  inherited Create;
  FTestList := Owner;
end;

function TOfTypeEnumeratorFactory<T,TFilter>.GetEnumerator: IEnumerator<TFilter>;
begin
  Result := TOfTypeEnumerator<T,TFilter>.Create(FTestList);
end;

{ TTestList<T> }

function TTestList<T>.OfType<TFilter>: IEnumerable<TFilter>;
begin
  Result := TOfTypeEnumeratorFactory<T,TFilter>.Create(self);
end;

end.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读