用Delphi 2010过滤枚举,让我们说我有声明如下一类:更好的方式来实现对从TList <TMyObject>
TMyList = TList<TMyObject>
对于这个列表德尔福好心为我们提供了一个枚举,所以我们可以这样写这样的:
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”函数的接口,然后我实现了一个实现接口的类,最后我在TMyList上写了一个返回接口的函数!而且我正在返回一个界面,因为我不想为手动释放这个非常简单的类而烦恼......不管怎样,这需要大量的输入。这里是如何做到这一点的样子:
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;
使用这个我终于可以写:
你知不知道这样做的更好的办法?也许德尔福支持一种直接调用GetEnumerator的方法?
后来编辑:
我决定用使用匿名方法实现枚举和使用贾布尔的“记录”工厂还保存其他类的罗伯特·爱的想法。这使我可以创建一个全新的枚举器,并使用代码完成,只需在函数中使用几行代码,不需要新的类声明。
这里是我的通用枚举的声明方式,在库单元:
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;
感谢这一点,现在实现对类的枚举器支持变得更容易了。如果你想使用'for obj in list do'之类的东西,那么只需像这样声明GetEnumerator():'function GetEnumerator:TEnumGenericAnonim',并且在实现中只需在Create语句的最后添加'.GetEnumerator'即可。 –
Sharken
2012-02-20 07:53:52