いいえ、これは実際には共分散ではありません。これは単なるインタフェースの実装です。具体的には、の割り当て互換性の例であるです。 Car
クラスはICarInterface
インターフェイスを実装しているため、ICarInterface
の変数にCar
オブジェクトを割り当てることができます。より具体的なタイプ()のオブジェクトは、より具体的でないタイプ(ICarInterface
)の記憶領域に割り当てられました。これは、2つのタイプが割り当ての目的で互換性があるために機能します。
共分散はわずかに異なります。型の関係は、より具体的なものからより一般的なものへの型の順序を保持するならば、共変(covariant)です。たとえば、IEnumerable<T>
はタイプT
に対して共変ですので、タイプIEnumerable<Vehicle>
(より一般的)とIEnumerable<Car>
(より具体的)の順序が保持されます。 (この例では、もちろんCar
がVehicle
のサブクラスであると仮定しています)。
Eric Lippert has written an excellent article that distinguishes between covariance and assignment-compatibility。わずかに技術的、理論的になりますが、間違いなくそれを読むべきです。私はそれをここでさらに要約しようとすることで正義をしません。
少なくとも私の考えでは分かりやすい例は、戻り値の共分散です。これは、派生クラスの基底クラスメソッドのオーバーライドによって、より具体的な型が返される場所です。たとえば:Savanna
とOcean
:
abstract class Habitat
{
public abstract Animal ApexPredator();
}
class Savanna : Habitat
{
public override Lion ApexPredator()
{ ... }
}
class Ocean : Habitat
{
public override Shark ApexPredator()
{ ... }
}
この例では、抽象クラスHabitat
は、2つの具象サブクラスを持っています。すべての生息地はApexPredator
です。タイプはAnimal
です。しかし、Savanna
オブジェクトでは、頂点の捕食者はLion
ですが、Ocean
オブジェクトでは、頂点捕食者はShark
です。 Lion
とShark
の両方がAnimal
のタイプであるため、これは法的で安全です。
残念ながら、C#は戻り値の共分散をサポートしていません。ただし、C++(C++/CLIを含む)、Java、およびその他のオブジェクト指向言語でサポートされています。
ここにいくつかあります。concrete examples of covarianceです。
これはありません。ジェネリックに関連しています。だから既にそれにはたくさんの質問があります。 – nawfal
私はそれを得ることはできません、それはジェネリックスに厳密に関連しているのはなぜですか?私の例では、CarはICarInterfaceから継承しています。次のような暗黙的なアップキャストは、それが共分散の例であることを意味しませんか?私は何が欠けていますか? ICarInterface car = new Car(); – Exocomp
これは***ではなく、重複しています。 Exocompは、彼が示している特定のコードが共分散の実例のリストではなく、共分散の例(そしてなぜ/なぜそうではないか)を求めています。それは共分散が何であるかを説明する質問の重複かもしれないが、それは選ばれたものではない。 Reopening ... –