Implementing List Enumerator OfType in Delphi

前端 未结 2 1924
执念已碎
执念已碎 2020-12-23 21:56

I am using Delphi XE to implement an enumerator that allows filtering the elements of the list by type. I have quickly assembled a test unit as follows:

uni         


        
2条回答
  •  再見小時候
    2020-12-23 22:33

    A worked version using system.IEnumerable and system.IEnumerator

    unit uTestList;
    
    interface
    
    uses Generics.Collections;
    
    type
      TListItemBase = class(TObject)
      end; { TListItemBase }
    
      TListItemChild1 = class(TListItemBase)
      end;
    
      TListItemChild2 = class(TListItemBase)
      end;
    
      TTestList = class;
    
      TOfTypeEnumerator = class(TInterfacedObject, IEnumerator, IEnumerator)
      private
        FTestList : TList;
        FIndex : Integer;
      protected
        constructor Create(Owner : TList); overload;
    
        function GetCurrent: TObject;
        function GenericGetCurrent : TFilter;
        function MoveNext : Boolean;
        procedure Reset;
    
        function IEnumerator.GetCurrent = GenericGetCurrent;
      end;
    
      TOfTypeEnumeratorFactory = class(TInterfacedObject, IEnumerable, IEnumerable)
      private
        FTestList : TList;
      public
        constructor Create(Owner : TList); overload;
        function GetEnumerator : IEnumerator;
        function GenericGetEnumerator : IEnumerator;
        function IEnumerable.GetEnumerator = GenericGetEnumerator;
      end;
    
      TTestList = class(TList)
      public
        function OfType() : IEnumerable;
      end; { TTestList }
    
    
    implementation
    
    { TOfTypeEnumerator }
    
    constructor TOfTypeEnumerator.Create(Owner: TList);
    begin
      inherited Create;
      FTestList := Owner;
      FIndex := -1;
    end;
    
    function TOfTypeEnumerator.GenericGetCurrent: TFilter;
    begin
      Result := TFilter(TObject(FTestList[FIndex]));
    end;
    
    function TOfTypeEnumerator.GetCurrent: TObject;
    begin
      Result := TObject( FTestList[FIndex] );
    end;
    
    function TOfTypeEnumerator.MoveNext: Boolean;
    begin
      repeat
        Inc(FIndex);
      until (FIndex >= FTestList.Count) or FTestList[FIndex].InheritsFrom(TFilter);
      Result := FIndex < FTestList.Count;
    end;
    
    procedure TOfTypeEnumerator.Reset;
    begin
      FIndex := -1;
    end;
    
    { TOfTypeEnumeratorFactory }
    
    constructor TOfTypeEnumeratorFactory.Create(Owner: TList);
    begin
      inherited Create;
      FTestList := Owner;
    end;
    
    function TOfTypeEnumeratorFactory.GetEnumerator: IEnumerator;
    begin
      Result := GenericGetEnumerator;
    end;
    
    function TOfTypeEnumeratorFactory.GenericGetEnumerator: IEnumerator;
    begin
      Result := TOfTypeEnumerator.Create(FTestList);
    end;
    
    { TTestList }
    
    function TTestList.OfType: IEnumerable;
    begin
      Result := TOfTypeEnumeratorFactory.Create(self);
    end;
    
    end.
    

    A test procedure:

    var
      MyElem: TListItemBase;
      MyElem1: TListItemChild1;
      MyElem2: TListItemChild2;
    begin
      Memo1.Clear;
      for MyElem in FTestList.OfType() do
      begin
        Memo1.Lines.Add('----------');
      end;
      for MyElem1 in FTestList.OfType() do
      begin
        Memo1.Lines.Add('==========');
      end;
      for MyElem2 in FTestList.OfType() do
      begin
        Memo1.Lines.Add('++++++++++');
      end;
    

提交回复
热议问题