for ... in with interface

Flo*_*och 1 delphi enumeration interface delphi-xe6

我正在尝试浏览一个对象列表,但我只想提供由我的对象实现的接口.

我有两种情况:只是在内部列举我的列表(这不是一个大问题,我可以只使用对象而不是接口)和一个属性.

ITemplate = interface
  ...
end;

TTemplate = class (TInterfacedObject, ITemplate)
  ...
end;

TMyClass = class
strict private
  FTemplates: TObjectList<TTemplate>;
  function GetTemplates: IEnumerable<ITemplate>;
  ...
public
  property Templates: IEnumerable<ITemplate> read GetTemplates;

...

procedure TMyClass.LoopTroughInternally;
var
  template: ITemplate;
begin
  for template in FTemplates do  // isn't working, of course
    foobar(template);
end;

function TMyClass.GetTemplates: IEnumerable<ITemplate>;
begin
  // dunno what to do here...
end;
Run Code Online (Sandbox Code Playgroud)

有没有办法提供这个枚举器而不实现特定的IEnumerable?

Dav*_*nan 7

采用面值,您可以将局部变量更改template为类型TTemplate,然后就完成了.如果此代码是内部代码,那么就没有必要做任何其他事情了.

但是,你似乎有更大的问题.

type
  TTemplate = class(TInterfacedObject, ITemplate)
    ...
  end;

....

FTemplates: TObjectList<TTemplate>;
Run Code Online (Sandbox Code Playgroud)

这是一个大错误.从您继承时,TInterfacedObject您说生命周期由接口引用计数管理.这意味着您必须停止使用非引用计数引用.因为它们容易变得陈旧.当您使用引用时,您将使用非引用计数TTemplate引用.您通过使用TObjectList<T>哪些是关于生命周期管理来复合事物.

逃避这种情况的简单方法是使用接口列表而不是它TObjectList<T>.

FTemplates: TList<ITemplate>;
Run Code Online (Sandbox Code Playgroud)

现在,在这一点上,你已经完成了,因为你确实可以写作

for template in FTemplates do
Run Code Online (Sandbox Code Playgroud)

哪里templateITemplate.