我有一个TList<TForm>类型的列表。我需要将其转换为TList<TObject>,如下所示:
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。
发布于 2014-02-10 14:33:22
好的,您的代码可以工作,但在我看来它有点可疑。简单地说,演员阵容是不合法的,因为
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等等。这样,您将调用对象的实际方法。
https://stackoverflow.com/questions/21677081
复制相似问题