首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >将TList<T:class>铸造为TList<W:class>

将TList<T:class>铸造为TList<W:class>
EN

Stack Overflow用户
提问于 2014-02-10 12:20:03
回答 1查看 1.5K关注 0票数 2

我有一个TList<TForm>类型的列表。我需要将其转换为TList<TObject>,如下所示:

代码语言:javascript
复制
procedure mainForm.testCast;
var
  listT: TList<TForm>;
  listW: TList<TObject>;
  obj: TObject;
begin
  listT := TList<TForm>.create;
  listT.add(form1);
  listT.add(form2);

  listW := TList<TObject>(listT);  // Casting is OK

  // This works, but is this fine?
  for obj in listW do
    memo1.lines.add(obj.className);

end;

该示例按预期工作,但在泛型列表之间进行这样的转换可以吗?这会不会导致一些数据结构的损坏等?我只将它用于循环(DoGetEnumerator)目的和一些字符串检查,即我不会添加/删除项。

真正的功能要复杂得多。它在listT中使用RTTI获得对TValue的引用。主要目标不是链接我的单元中的FMX.Forms

更新: incompatible types?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2014-02-10 14:33:22

好的,您的代码可以工作,但在我看来它有点可疑。简单地说,演员阵容是不合法的,因为

代码语言:javascript
复制
TList<TForm>.InheritsFrom(TList<TObject>)

都是假的。因此,TList<TForm>对象不是TList<TObject>。如果是的话,那就不需要演员了。

之所以如此,是因为Delphi的泛型类型是不变的。更多细节可以在这里找到:Why is a class implementing an interface not compatible with the interface type when used in generics?

如果您很难理解为什么设计器使泛型类型不变,那么请考虑一下在代码中编写listW.Add(TObject.Create)的效果。想想它对TList<TForm>类型的真正的底层对象意味着什么。

所以语言不会对你有任何承诺。你是在冒险超越它的保证。这两种不相关类型的实现恰好兼容到您的代码可以工作。但这实际上只是实施的一个意外。

因为您已经在使用RTTI,所以我建议您使用RTTI迭代列表。您可以使用RTTI调用GetEnumerator等等。这样,您将调用对象的实际方法。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/21677081

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档