为什么是TGeneric< Base>和TGeneric不兼容的类型 [英] Why are TGeneric<Base> and TGeneric<Descendant> incompatible types?

查看:289
本文介绍了为什么是TGeneric< Base>和TGeneric不兼容的类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我开始在Delphi 2010中使用泛型,但编译这段代码时有问题:

  TThreadBase = class(TThread)
...
end;

TThreadBaseList< T:TThreadBase> = class(TObjectList< T>)
...
end;

TDataProviderThread = class(TThreadBase)
...
end;

TDataCore = class(TInterfacedObject,IDataCore)
private
FProviders:TThreadBaseList< TDataProviderThread> ;;
...
end;

然后我有一些嵌套的过程:

 过程MakeAllThreadsActive(aThreads:TThreadBaseList< TThreadBase>); 
begin
...
end;

最后我想在TDataCore类的代码中调用此嵌套过程:

  MakeAllThreadsActive(FProviders); 

但编译器不想编译它,它表示('''括号被'()'):


[DCC错误] LSCore.pas(494):E2010不兼容的类型:
'TThreadBaseList TThreadBase)'和
'TThreadBaseList(TDataProviderThread)'


我不明白,虽然TDataProviderThread是TThreadBase的后代。 / p>

我不得不通过硬式类型转换修复它:

  MakeAllThreadsActive(TThreadBaseList< ; TThreadBase>(FProviders));有没有人知道编译器为什么会发出这个错误?

$ / code $ =h2_lin>解决方案

TDataProviderThread是TThreadBase的后代,但 TThreadBaseList< TDataProviderThread> 不是 TThreadBaseList< TThreadBase> 。这不是继承,它被称为协方差,虽然它似乎直觉上像同样的事情,但它不是,它必须单独支持。目前,Delphi不支持它,尽管希望在将来的版本中。



这是协方差问题的基本原因:如果您传递的功能要预期一个TThreadBase对象的列表,并且您传递一个TDataProviderThread对象的列表,没有什么可以阻止它调用。添加并将一些其他TThreadBase对象粘贴到不是TDataProviderThread的列表中,现在你已经有了所有的种类的丑陋问题。您需要编译器的特殊技巧,以确保不会发生这种情况,否则您将失去安全性。



编辑:这是一个可能的解决方案:让MakeAllThreadsActive进入一个通用的方法,像这样:

 过程MakeAllThreadsActive< T:TThreadBase>(aThreads:TThreadBaseList< T>); 

或者你可以做Uwe Raabe的建议。任何一个人都可以工作。


I have started using of generics in Delphi 2010 but I have a problem when compiling this piece of code:

TThreadBase = class( TThread )
...
end;

TThreadBaseList<T: TThreadBase> = class( TObjectList<T> )
...
end;

TDataProviderThread = class( TThreadBase )
...
end;

TDataCore = class( TInterfacedObject, IDataCore )
private
  FProviders: TThreadBaseList<TDataProviderThread>;
...
end;

Then I have some nested procedure:

procedure MakeAllThreadsActive(aThreads: TThreadBaseList<TThreadBase>);
begin
...
end;

And finally I want to call this nested procedure in the code of TDataCore class:

MakeAllThreadsActive(FProviders);

But compiler does not want to compile it and it says ('<>' brackets are replaced by '()'):

[DCC Error] LSCore.pas(494): E2010 Incompatible types: 'TThreadBaseList(TThreadBase)' and 'TThreadBaseList(TDataProviderThread)'

I do not understand it although TDataProviderThread is descendant of TThreadBase.

I had to fix it by hard typecasting:

MakeAllThreadsActive(TThreadBaseList<TThreadBase>(FProviders));

Does anybody know why the compiler says this error?

解决方案

TDataProviderThread is a descendant of TThreadBase, but TThreadBaseList<TDataProviderThread> is not a descendant of TThreadBaseList<TThreadBase>. That's not inheritance, it's called covariance, and though it seems intuitively like the same thing, it isn't and it has to be supported separately. At the moment, Delphi doesn't support it, though hopefully it will in a future release.

Here's the basic reason for the covariance problem: If the function you pass it to is expecting a list of TThreadBase objects, and you pass it a list of TDataProviderThread objects, there's nothing to keep it from calling .Add and sticking some other TThreadBase object into the list that's not a TDataProviderThread, and now you've got all sorts of ugly problems. You need special tricks from the compiler to make sure this can't happen, otherwise you lose your type safety.

EDIT: Here's a possible solution for you: Make MakeAllThreadsActive into a generic method, like this:

procedure MakeAllThreadsActive<T: TThreadBase>(aThreads: TThreadBaseList<T>);

Or you could do what Uwe Raabe suggested. Either one will work.

这篇关于为什么是TGeneric&lt; Base&gt;和TGeneric不兼容的类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆