gpt4 book ai didi

delphi - 在 TList 上实现过滤枚举器的更好方法

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

使用 Delphi 2010,假设我有一个这样声明的类:

TMyList = TList<TMyObject>

对于这个列表,Delphi 好心地为我们提供了一个枚举器,所以我们可以这样写:

var L:TMyList;
E:TMyObject;
begin
for E in L do ;
end;

问题是,我想这样写:

var L:TMyList;
E:TMyObject;
begin
for E in L.GetEnumerator('123') do ;
end;

也就是说,我希望能够使用某些条件为同一列表提供多个枚举器。不幸的是 for X in Z 的实现需要存在一个函数Z.GetEnumerator ,不带参数,返回给定的枚举器!为了避免这个问题,我定义了一个实现“GetEnumerator”函数的接口(interface),然后实现了一个实现该接口(interface)的类,最后在 TMyList 上编写了一个返回该接口(interface)的函数!我正在返回一个接口(interface),因为我不想为手动释放非常简单的类而烦恼......无论如何,这需要大量的输入。看起来是这样的:

TMyList = class(TList<TMyObject>)
protected

// Simple enumerator; Gets access to the "root" list
TSimpleEnumerator = class
protected
public
constructor Create(aList:TList<TMyObject>; FilterValue:Integer);

function MoveNext:Boolean; // This is where filtering happens
property Current:TTipElement;
end;

// Interface that will create the TSimpleEnumerator. Want this
// to be an interface so it will free itself.
ISimpleEnumeratorFactory = interface
function GetEnumerator:TSimpleEnumerator;
end;

// Class that implements the ISimpleEnumeratorFactory
TSimpleEnumeratorFactory = class(TInterfacedObject, ISimpleEnumeratorFactory)
function GetEnumerator:TSimpleEnumerator;
end;

public
function FilteredEnum(X:Integer):ISimpleEnumeratorFactory;
end;

使用这个我终于可以写:

var L:TMyList;
E:TMyObject;
begin
for E in L.FilteredEnum(7) do ;
end;

您知道更好的方法吗?也许Delphi确实支持直接使用参数调用GetEnumerator的方式?

稍后编辑:

我决定采用 Robert Love 的想法,即使用匿名方法实现枚举器并使用 gabr 的“记录”工厂来保存另一个类。这使我能够创建一个全新的枚举器,包含完整的代码,只需在函数中使用几行代码,不需要新的类声明。

以下是我的通用枚举器在库单元中的声明方式:

TEnumGenericMoveNext<T> = reference to function: Boolean;
TEnumGenericCurrent<T> = reference to function: T;

TEnumGenericAnonim<T> = class
protected
FEnumGenericMoveNext:TEnumGenericMoveNext<T>;
FEnumGenericCurrent:TEnumGenericCurrent<T>;
function GetCurrent:T;
public
constructor Create(EnumGenericMoveNext:TEnumGenericMoveNext<T>; EnumGenericCurrent:TEnumGenericCurrent<T>);

function MoveNext:Boolean;
property Current:T read GetCurrent;
end;

TGenericAnonEnumFactory<T> = record
public
FEnumGenericMoveNext:TEnumGenericMoveNext<T>;
FEnumGenericCurrent:TEnumGenericCurrent<T>;
constructor Create(EnumGenericMoveNext:TEnumGenericMoveNext<T>; EnumGenericCurrent:TEnumGenericCurrent<T>);
function GetEnumerator:TEnumGenericAnonim<T>;
end;

这是一种使用它的方法。在任何类上,我都可以添加这样的函数(并且我有意创建一个不使用 List<T> 的枚举器来显示此概念的强大功能):

type Form1 = class(TForm)
protected
function Numbers(From, To:Integer):TGenericAnonEnumFactory<Integer>;
end;

// This is all that's needed to implement an enumerator!
function Form1.Numbers(From, To:Integer):TGenericAnonEnumFactory<Integer>;
var Current:Integer;
begin
Current := From - 1;
Result := TGenericAnonEnumFactory<Integer>.Create(
// This is the MoveNext implementation
function :Boolean
begin
Inc(Current);
Result := Current <= To;
end
,
// This is the GetCurrent implementation
function :Integer
begin
Result := Current;
end
);
end;

以下是我如何使用这个新的枚举器:

procedure Form1.Button1Click(Sender: TObject);
var N:Integer;
begin
for N in Numbers(3,10) do
Memo1.Lines.Add(IntToStr(N));
end;

最佳答案

参见 DeHL ( http://code.google.com/p/delphilhlplib/ )。您可以编写如下所示的代码:

for E in List.Where(...).Distinct.Reversed.Take(10).Select(...)... etc. 

就像您在 .NET 中所做的那样(当然没有语法 linq)。

关于delphi - 在 TList<TMyObject> 上实现过滤枚举器的更好方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3177760/

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