Delphi 铸造TList<;T:class>;到TList<;W:等级>;

Delphi 铸造TList<;T:class>;到TList<;W:等级>;,delphi,casting,rtti,generic-collections,tlist,Delphi,Casting,Rtti,Generic Collections,Tlist,我有一个类型列表TList。我需要将其转换为TList,如下所示: 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<TO

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

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;
procedure mainForm.testCast;
变量
listT:TList;
listW:TList;
对象:对象;
开始
listT:=TList.create;
列表添加(表格1);
列表添加(表格2);
listW:=TList(listT);//铸造是好的
//这样行得通,但这样行吗?
对于列表中的obj,请执行以下操作:
备注1.lines.add(对象类名称);
结束;
该示例按预期工作,但在通用列表之间这样强制转换可以吗?这是否会导致数据结构损坏等? 我仅将其用于循环(
dogetemulator
)目的和一些字符串检查,即我不会添加/删除项

真正的函数稍微复杂一点。它在
TValue
中使用RTTI获取对
listT
的引用。 主要目标不是在我的单元中链接
FMX.Forms

更新:

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

TList<TForm>.InheritsFrom(TList<TObject>)
TList.InheritsFrom(TList)
这是错误的。因此
TList
对象不是
TList
。如果是,那么就不需要演员阵容了

这是因为Delphi的泛型类型是不变的。更多详细信息可在此处找到:

如果您有任何困难理解为什么设计器使泛型类型不变量,那么请考虑在代码中写入“代码> List.Advest.Addio.ToStudio.Cudio.<代码>的效果。想想它对类型为

TList
的真正底层对象意味着什么

所以语言对你没有任何承诺。你是在其担保范围之外冒险。碰巧这两种不相关类型的实现是兼容的,足以让代码正常工作。但这实际上只是执行过程中的一个意外


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

这很好,但有点粗略。我怀疑你在任何情况下都需要在这里使用石膏。您可以通过RTTI访问枚举器。由于
TForm
是从
TObject
派生而来的,
TList
是一个类型指针的通用列表,因此您所做的事情没有错。也就是说,使用基类中的方法。@LURD我认为这是不对的
TList
不是
TList
的基类。您将发现
TList是TList
的计算结果为
False
。公共基础是
TList
。另一种思考方式。如果它只是使用基类中的方法,为什么需要强制转换?@LURD抱歉,我在评论中的代码错了。当然,
在这里是不好的,因为它们都是类。我的意思是
TList.InheritsFrom(TList)
@DavidHeffernan,基类主要是
TForm
vs
TObject
。我希望
TList
的行为方式与
TList
类似,而这对于任何
TList
都不是真的。谢谢@David Heffernan!我的目标是使用RTTI枚举表单的子级。枚举数返回TEnumerator,但我不想在单位中包含FMX.Types。所以我想把结果转换成像TEnumerator这样的东西,这就引出了上面的问题。你不需要转换成具体的类型。你需要完全融入RTTI的世界。您的代码可以工作,但这取决于实现细节。“您需要完全融入RTTI的世界”-好的一点:)顺便说一句,我的想法很简单(可能是错误的)逻辑是:如果W&T是一个类的实例,那么您可以将它们强制转换为一个共同的祖先,即TObject,前提是您确定它们是类实例。
W
T
有一个共同的祖先。但这不是我们正在处理的问题。它是
TList
TList
,我们进入了泛型不变性。我对我链接到的问题的回答以及其中的链接值得一读。也许我会比我在那个问题上和提问者一起更成功地帮助你们理解一般差异!;-)