gpt4 book ai didi

delphi - 如何为从 TDictionary 派生的类创建自定义枚举器?

转载 作者:行者123 更新时间:2023-12-03 14:43:44 24 4
gpt4 key购买 nike

我已经定义了一个从 TDictionary 派生的集合,并且需要定义一个应用附加过滤器的自定义枚举器。

我陷入困境,因为我无法访问 TDictionary FItems 数组(它是私有(private)的),因此我无法定义 MoveNext 方法

您将如何在从 TDictionary 派生的类上重新定义过滤枚举器?

这是一个简单的代码来说明我想要做什么:

TMyItem = class(TObject)
public
IsHidden:Boolean; // The enumerator should not return hidden items
end;
TMyCollection<T:TMyItem> = class(TDictionary<integer,T>)
public
function GetEnumerator:TMyEnumerator<T>; // A value filtered enumerator
type
TMyEnumerator = class(TEnumerator<T>)
private
FDictionary: TMyCollection<integer,T>;
FIndex: Integer;
function GetCurrent: T;
protected
function DoGetCurrent: T; override;
function DoMoveNext: Boolean; override;
public
constructor Create(ADictionary: TMyCollection<integer,T>);
property Current: T read GetCurrent;
function MoveNext: Boolean;
end;
end;

function TMyCollection<T>.TMyEnumerator.MoveNext: Boolean;
begin
// In below code, FIndex is not accessible, so I can't move forward until my filter applies
while FIndex < Length(FDictionary.FItems) - 1 do
begin
Inc(FIndex);
if (FDictionary.FItems[FIndex].HashCode <> 0)
and not(FDictionary.FItems[FIndex].IsHidden) then // my filter
Exit(True);
end;
Result := False;
end;

最佳答案

您可以将枚举器基于 TDictionary 的枚举器,因此您实际上不需要访问 FItems。即使您按照 Barry 的建议围绕 TDictionary 编写了一个包装类,这仍然有效。枚举器看起来像这样:

TMyEnumerator = class
protected
BaseEnumerator: TEnumerator<TPair<Integer, T>>; // using the key and value you used in your sample
public
function MoveNext:Boolean;
property Current:T read GetCurrent;
end;

function TMyEnumerator.MoveNext:Boolean;
begin
Result := BaseEnumerator.MoveNext;
while Result and (not (YourTestHere)) do // ie: the base enumerator returns everything, reject stuff you don't like
Result := BaseEnumerator.MoveNext;
end;

function TMyEnumerator.Current: T;
begin
Result := BaseEnumerator.Current.Value; // Based on your example, it's value you want to extract
end;

这是一个完整的 100 行控制台应用程序,演示了这一点:

program Project23;

{$APPTYPE CONSOLE}

uses
SysUtils, Generics.Collections;

type

TMyType = class
public
Int: Integer;
constructor Create(anInteger:Integer);
end;

TMyCollection<T:TMyType> = class(TDictionary<integer,T>)
strict private
type
TMyEnumerator = class
protected
BaseEnum: TEnumerator<TPair<Integer,T>>;
function GetCurrent: T;
public
constructor Create(aBaseEnum: TEnumerator<TPair<Integer,T>>);
destructor Destroy;override;

function MoveNext:Boolean;
property Current:T read GetCurrent;
end;
public
function GetEnumerator: TMyEnumerator;
end;

{ TMyCollection<T> }

function TMyCollection<T>.GetEnumerator: TMyEnumerator;
begin
Result := TMyEnumerator.Create(inherited GetEnumerator);
end;

{ TMyType }

constructor TMyType.Create(anInteger: Integer);
begin
Int := anInteger;
end;

{ TMyCollection<T>.TMyEnumerator }

constructor TMyCollection<T>.TMyEnumerator.Create(aBaseEnum: TEnumerator<TPair<Integer, T>>);
begin
BaseEnum := aBaseEnum;
end;

function TMyCollection<T>.TMyEnumerator.GetCurrent: T;
begin
Result := BaseEnum.Current.Value;
end;

destructor TMyCollection<T>.TMyEnumerator.Destroy;
begin
BaseEnum.Free;
inherited;
end;

function TMyCollection<T>.TMyEnumerator.MoveNext:Boolean;
begin
Result := BaseEnum.MoveNext;
while Result and ((BaseEnum.Current.Value.Int mod 2) = 1) do
Result := BaseEnum.MoveNext;
end;

var TMC: TMyCollection<TMyTYpe>;
V: TMyType;

begin
try
TMC := TMyCollection<TMyType>.Create;
try
// Fill TMC with some values
TMC.Add(1, TMyType.Create(1));
TMC.Add(2, TMyType.Create(2));
TMC.Add(3, TMyType.Create(3));
TMC.Add(4, TMyType.Create(4));
TMC.Add(5, TMyType.Create(5));
TMC.Add(6, TMyType.Create(6));
TMC.Add(7, TMyType.Create(7));
TMC.Add(8, TMyType.Create(8));
// Filtered-enum
for V in TMC do
WriteLn(V.Int);
ReadLn;
finally TMC.Free;
end;
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
end.

关于delphi - 如何为从 TDictionary 派生的类创建自定义枚举器?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6044300/

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