如何为从 TDictionary 派生的类创建自定义枚举器?
我已经定义了一个从 TDictionary 派生的集合,并且需要定义一个应用附加过滤器的自定义枚举器。
我陷入困境,因为我无法访问 TDictionary FItems 数组(它是私有的),因此我无法定义 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;
I have defined a collection derived from TDictionary, and need to define a custom enumerator that apply an additional filter.
I'm stuck as I can't access the TDictionary FItems array (it is private) so I can't define the MoveNext method
How would you proceed to redefine a filtered enumerator on a class derived from TDictionary?
Here's a simple code to illustrate what I want to do:
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;
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您可以将枚举器基于
TDictionary
的枚举器,因此您实际上不需要访问FItems
。即使您按照 Barry 的建议围绕TDictionary
编写了一个包装类,这仍然有效。枚举器看起来像这样:这是一个完整的 100 行控制台应用程序,演示了这一点:
You can base your Enumerator on
TDictionary
's enumerator, so you don't actually need access toFItems
. This works even if you write a wrapper class aroundTDictionary
as Barry suggests. The enumerator would look like this:And here's a complete, 100 lines console application that demonstrates this:
您应该编写一个包装 TDictionary 的类,而不是直接继承它。
TDictionary
可以继承的唯一原因是可以定义TObjectDictionary
并与其保持多态性。也就是说,通过重写 TDictionary 的唯一正确支持是自定义从字典中删除键和值时发生的情况(因此可能需要释放它们)。You should write a class that wraps
TDictionary
rather than inherits from it directly. The only reasonTDictionary
can be inherited from at all is so thatTObjectDictionary
could be defined and stay polymorphic with it. That is, the only proper support through overridingTDictionary
is to customize what happens when keys and values are removed from the dictionary (so they might need to be freed).