13

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;

次に、ネストされたプロシージャがあります。

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

そして最後に、TDataCoreクラスのコードでこのネストされたプロシージャを呼び出したいと思います。

MakeAllThreadsActive(FProviders);

しかし、コンパイラーはそれをコンパイルすることを望まず、('<>'括弧は'()'に置き換えられます)と言います:

[DCCエラー]LSCore.pas(494):E2010互換性のないタイプ:'TThreadBaseList(TThreadBase)'および'TThreadBaseList(TDataProviderThread)'

TDataProviderThreadはTThreadBaseの子孫ですが、わかりません。

ハードタイプキャストで修正する必要がありました。

MakeAllThreadsActive(TThreadBaseList<TThreadBase>(FProviders));

コンパイラがこのエラーを言う理由を誰かが知っていますか?

4

2 に答える 2

22

TDataProviderThread は TThreadBase の子孫ですが、 の子孫でTThreadBaseList<TDataProviderThread>はありませんTThreadBaseList<TThreadBase>。それは継承ではなく、共分散と呼ばれ、直感的には同じように見えますが、そうではなく、個別にサポートする必要があります。現時点では、Delphi ではサポートされていませんが、将来のリリースでサポートされることを願っています。

共分散の問題の基本的な理由は次のとおりです。渡す関数が TThreadBase オブジェクトのリストを想定していて、それに TDataProviderThread オブジェクトのリストを渡す場合、.Add を呼び出して他の TThreadBase オブジェクトを貼り付けないようにするものは何もありません。 TDataProviderThread ではないリストであり、あらゆる種類の厄介な問題が発生しています。これが起こらないようにするには、コンパイラからの特別なトリックが必要です。そうしないと、型の安全性が失われます。

編集:これはあなたのための可能な解決策です: MakeAllThreadsActive を次のように汎用メソッドにします:

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

または、Uwe Raabe が提案したことを行うこともできます。どちらでも動作します。

于 2009-11-06T14:02:19.703 に答える
6

タイプ

TList <TBase>

の親タイプではありません

TList <TChild>

ジェネリックはそのように使用することはできません。

于 2009-11-06T14:01:08.993 に答える