我已经定义了一个从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;
感谢这个完整的示例,我现在更好地理解如何使用枚举器。我还发现,包装枚举器有一个巨大的性能损失(在我的示例应用程序中,对象查询需要常规TDictionary枚举器2.2ms,包装枚举器3.3ms(+ 50%!),而不应用任何过滤器)。 – user315561 2011-05-19 07:24:21
@ user315561,什么需要2.2ms?在现代CPU上2.2毫秒是一个可怕的长时间,你可能错过了一些东西;并且这使得包装的枚举器的3.3ms结果同样是错误的。 – 2011-05-19 07:45:16
我同意我的数字在背景下提供,并不相关。用例是对75000个对象集合的查询,按顺序浏览一个简单的相等过滤器,并将850个匹配对象添加到新的结果集合中。我想在这里强调的是枚举器封装的成本惩罚(在相同的用例中),这是相关并且很好知道的。 – user315561 2011-05-19 10:35:44