【发布时间】:2010-04-29 21:08:13
【问题描述】:
好的,这可能会令人困惑。我想要做的是使用枚举器只返回基于类类型的通用列表中的某些项目。
给定以下层次结构:
type
TShapeClass = class of TShape;
TShape = class(TObject)
private
FId: Integer;
public
function ToString: string; override;
property Id: Integer read FId write FId;
end;
TCircle = class(TShape)
private
FDiameter: Integer;
public
property Diameter: Integer read FDiameter write FDiameter;
end;
TSquare = class(TShape)
private
FSideLength: Integer;
public
property SideLength: Integer read FSideLength write FSideLength;
end;
TShapeList = class(TObjectList<TShape>)
end;
如何扩展 TShapeList 以便可以执行类似于以下操作的操作:
procedure Foo;
var
ShapeList: TShapeList;
Shape: TShape;
Circle: TCircle;
Square: TSquare;
begin
// Create ShapeList and fill with TCircles and TSquares
for Circle in ShapeList<TCircle> do begin
// do something with each TCircle in ShapeList
end;
for Square in ShapeList<TSquare> do begin
// do something with each TSquare in ShapeList
end;
for Shape in ShapeList<TShape> do begin
// do something with every object in TShapeList
end;
end;
我尝试使用 Primoz Gabrijelcic 在Parameterized Enumerators 上的修改版本扩展TShapeList,使用工厂记录如下:
type
TShapeList = class(TObjectList<TShape>)
public
type
TShapeFilterEnumerator<T: TShape> = record
private
FShapeList: TShapeList;
FClass: TShapeClass;
FIndex: Integer;
function GetCurrent: T;
public
constructor Create(ShapeList: TShapeList);
function MoveNext: Boolean;
property Current: T read GetCurrent;
end;
TShapeFilterFactory<T: TShape> = record
private
FShapeList: TShapeList;
public
constructor Create(ShapeList: TShapeList);
function GetEnumerator: TShapeFilterEnumerator<T>;
end;
function FilteredEnumerator<T: TShape>: TShapeFilterFactory<T>;
end;
然后我将Foo修改为:
procedure Foo;
var
ShapeList: TShapeList;
Shape: TShape;
Circle: TCircle;
Square: TSquare;
begin
// Create ShapeList and fill with TCircles and TSquares
for Circle in ShapeList.FilteredEnumerator<TCircle> do begin
// do something with each TCircle in ShapeList
end;
for Square in ShapeList.FilteredEnumerator<TSquare> do begin
// do something with each TSquare in ShapeList
end;
for Shape in ShapeList.FilteredEnumerator<TShape> do begin
// do something with every object in TShapeList
end;
end;
但是,当我尝试编译 Foo about Incompatible types: TCircle and TShape 时,Delphi 2010 抛出错误。如果我注释掉 TCircle 循环,我会收到关于 TSquare 的类似错误。如果我也将TSquare 循环注释掉,代码就会编译并工作。嗯,它的工作原理是枚举每个对象,因为它们都来自TShape。奇怪的是编译器指示的行号比我的文件末尾多 2 行。在我的演示项目中,它表示第 177 行,但只有 175 行。
有什么办法可以做到这一点吗?我希望能够直接分配给 Circle,而无需经过任何类型转换或检查我的 for 循环本身。
【问题讨论】:
标签: delphi generics filter delphi-2010 enumerator