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

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

问题描述

我已经开始在 Delphi 2010 中使用泛型,但是在编译这段代码时遇到了问题:

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;

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

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 错误] LSCore.pas(494): E2010 不兼容类型:'TThreadBaseList(TThreadBase)' 和'TThreadBaseList(TDataProviderThread)'

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

我不明白,虽然 TDataProviderThread 是 TThreadBase 的后代.

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 是 TThreadBase 的后代,但 TThreadBaseList 不是 TThreadBaseList 的后代代码>.这不是继承,它被称为协方差,虽然它在直觉上看起来像是同一件事,但它不是,必须单独支持.目前,Delphi 不支持它,但希望在未来的版本中会支持.

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.

这是协方差问题的基本原因:如果您传递给它的函数需要一个 TThreadBase 对象列表,而您传递给它一个 TDataProviderThread 对象列表,则没有什么可以阻止它调用 .Add 并粘贴一些其他对象将 TThreadBase 对象放入不是 TDataProviderThread 的列表中,现在您遇到了各种丑陋的问题.您需要来自编译器的特殊技巧来确保不会发生这种情况,否则您将失去类型安全性.

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.

这是一个可能的解决方案:使 MakeAllThreadsActive 成为通用方法,如下所示:

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

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

或者你可以按照 Uwe Raabe 的建议去做.任何一个都可以.

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

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

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