gpt4 book ai didi

delphi - 在 Delphi 中实现 List Enumerator OfType

转载 作者:行者123 更新时间:2023-12-03 14:34:18 25 4
gpt4 key购买 nike

我正在使用 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, TFilter> = class(TInterfacedObject, 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 之上实现这个问题时,我遇到了类似的编译器问题,但我想我应该在这里提出一个简单的、普通的 Delphi 问题。

有人有真正可以编译的替代实现吗?

谢谢。

最佳答案

您不想使用 System.pas 中的 IEnumerator ,相信我。这个东西带来了很多麻烦,因为它继承自 IEnumerator,并且具有不同结果的 GetCurrent 方法(对于 IEnumerator 为 TObject,对于 IEnumerator 为 T)。

更好地定义您自己的 IEnumerator :

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

与 IEnumerable 相同。我想说定义你自己的 IEnumerable :

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

如果您在 TOfTypeEnumerator 中使用它,您可以删除导致 ICE 的方法解析子句。

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

  • 在构造函数中调用刚刚继承的构造函数会尝试调用祖先类中不存在的具有相同签名的构造函数。所以改成继承Create即可。

  • 不要使用 IEnumerable,而是使用 IEnumerable ,因为这就是您想要枚举的内容

  • 不要使用仅允许用于对象的方法和强制转换,或者在 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> }

constructor 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> }

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

关于delphi - 在 Delphi 中实现 List Enumerator OfType<T>,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10657475/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com