我有2个接口..
IInterfaceA = interface
.....
End;
IInterfaceB = interface
['{834D7063-AE8F-40BF-B1E7-E0806EB991C7}']
Function getA (A: Integer): IInterfaceA;
Function getList: TList <IInterfaceA>;
End;
TClassA = class (TInterfacedObject, IInterfaceA)
....
End
TClassB = class (TInterfacedObject, IInterfaceB)
Function getA (A: Integer): IInterfaceA;
Function getList: TList <IInterfaceA>;
End;
// It works
Function TClassB.getA (A: Integer): IInterfaceA;
Begin
Result: = Manager.Find <TClassA> .Add (Linq.Eq ('fieldxxx', A.ToString).) UniqueResult;
End;
以下不起作用并产生此错误:
E2010不兼容的类型:
'System.Generics.Collections.TList <IInterfaceA>'
和'System.Generics.Collections.TObjectList <TClassB>'
Function TClassB.getList: TList <IInterfaceA>;
Begin
// The TClassA class implements the interface IInterfaceA
Result: = Manager.Find <TClassA> .List;
End;
我该如何解决?
答案 0 :(得分:4)
从错误信息中可以明显看出问题是什么。 Manager.Find<TClassA>.List
正在返回TObjectList<TClassB>
(为什么TClassB
而不是TClassA
?),这与TList<IInterfaceA>
的类型不同,因此无法返回 - 是
要使代码编译,您需要更像这样的东西:
Function TClassB.getList: TList<IInterfaceA>;
var
Obj: TClassA;
begin
// The TClassA class implements the interface IInterfaceA
Result := TList<IInterfaceA>.Create;
try
for Obj in Manager.Find<TClassA>.List do
Result.Add(Obj as IInterfaceA);
except
Result.Free;
raise;
end;
end;
然而,这引入了两个问题:
Result
的内存管理。由于返回的TList<IInterfaceA>
不归任何人所有,因此调用者在使用它时必须手动Free
。如果Manager
拥有Find()
返回的列表,则原始代码中的情况不是这样。如果没有,那么您的原始代码就会遇到这个问题。
列表中对象的内存管理。由于对象是由TInterfacedObject
引用计数的,因此当它们的IInterfaceA
接口添加到返回的TList<IInterfaceA>
时,它们的引用计数将递增,然后在从列表中删除它们时递减。由于Manager.Find()
返回的原始列表包含TClassA
个对象指针而不是IInterfaceA
接口指针,因此无法正确管理对象的引用计数。释放/清除TList<IInterfaceA>
后,您的对象可能会过早释放(除非您将TClassA
指针添加到Manager
列表时手动增加其引用计数,并且删除指针时手动递减它们。)
否则,您需要更改Manager.Find()
以返回TList<IInterfaceA>
而不是TObjectList<TClassB>
。
您应该考虑重新考虑您的Manager
设计。混合对象指针和接口对象的接口指针是不好的设计。处理接口对象时,应该使用接口来处理所有事情。否则,为避免出现问题,您的实现类需要覆盖_AddRef()
和_Release()
方法以禁用引用计数。