2016-06-19 14 views
6

インターフェイスについては、C#の共分散の概念については明確ではありません。厳密に以下の私の例に基づいて、これは共分散の例です、なぜ、なぜそうではないのかを記述してください。C#とインターフェイスの共分散

class Program 
{ 
    static void Main() 
    { 
     ICarInterface car = new Car(); 
    } 
} 

interface ICarInterface 
{ 
    void Start(); 
} 

class Car : ICarInterface 
{ 
    public void Start() 
    { 

    } 
} 
+0

これはありません。ジェネリックに関連しています。だから既にそれにはたくさんの質問があります。 – nawfal

+0

私はそれを得ることはできません、それはジェネリックスに厳密に関連しているのはなぜですか?私の例では、CarはICarInterfaceから継承しています。次のような暗黙的なアップキャストは、それが共分散の例であることを意味しませんか?私は何が欠けていますか? ICarInterface car = new Car(); – Exocomp

+0

これは***ではなく、重複しています。 Exocompは、彼が示している特定のコードが共分散の実例のリストではなく、共分散の例(そしてなぜ/なぜそうではないか)を求めています。それは共分散が何であるかを説明する質問の重複かもしれないが、それは選ばれたものではない。 Reopening ... –

答えて

0

これは共分散の例ではなく、単なる多型の簡単な例です。 Hereあなたは共分散と多型の違いを見つけることができます

+0

私があなたに渡したリンクに行ったのは、.NET 4を使用した例があり、正直なところ、私の例は共分散の例ではないと答えていません。 – Exocomp

2

いいえ、これは実際には共分散ではありません。これは単なるインタフェースの実装です。具体的には、の割り当て互換性の例であるです。 CarクラスはICarInterfaceインターフェイスを実装しているため、ICarInterfaceの変数にCarオブジェクトを割り当てることができます。より具体的なタイプ()のオブジェクトは、より具体的でないタイプ(ICarInterface)の記憶領域に割り当てられました。これは、2つのタイプが割り当ての目的で互換性があるために機能します。

共分散はわずかに異なります。型の関係は、より具体的なものからより一般的なものへの型の順序を保持するならば、共変(covariant)です。たとえば、IEnumerable<T>はタイプTに対して共変ですので、タイプIEnumerable<Vehicle>(より一般的)とIEnumerable<Car>(より具体的)の順序が保持されます。 (この例では、もちろんCarVehicleのサブクラスであると仮定しています)。

Eric Lippert has written an excellent article that distinguishes between covariance and assignment-compatibility。わずかに技術的、理論的になりますが、間違いなくそれを読むべきです。私はそれをここでさらに要約しようとすることで正義をしません。


少なくとも私の考えでは分かりやすい例は、戻り値の共分散です。これは、派生クラスの基底クラスメソッドのオーバーライドによって、より具体的な型が返される場所です。たとえば:SavannaOcean

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です。 LionSharkの両方がAnimalのタイプであるため、これは法的で安全です。

残念ながら、C#は戻り値の共分散をサポートしていません。ただし、C++(C++/CLIを含む)、Java、およびその他のオブジェクト指向言語でサポートされています。

ここにいくつかあります。concrete examples of covarianceです。

+0

こんにちはコーディ、あなたの例は、戻り値の型共分散をサポートしていないC#について少し考えていたと私はあなたの言葉を具体的にその例で参照してください。ジェネリックスを使ってその問題を解決できると思います。戻り値の型にはプレースホルダを使用しますが、とにかくトピックから離れすぎないようにしてください。私の質問は、私の例が共変でない理由です。あなたはそれが「割り当ての互換性」の一例だと言いますが、それが共変ではない理由を説明していませんか? 「割り当ての互換性」が共分散である可能性はありますが、すべての共分散が「割り当ての互換性」ではないのですか? – Exocomp

+0

@exo戻り値型共分散の代わりにジェネリックを使用することは本当にありません。ジェネリックスは、リレーションシップがリターン型共分散の完全なポイントである場合、型間には関係がないことを意味します。 C#での戻り型共分散をエミュレートする標準的な方法は、メソッド隠蔽です。オーバーライドメソッドを 'protected'にして、オーバーライドされたメソッドを隠す(' new') 'public'メソッドを追加します。それについてさらに質問がある場合は、新しい質問をする必要があります。 –

+0

@exoあなたの他の質問については... *「私の質問は私の例が共変動ではなかったのですが、それは「割り当ての互換性」の例だと言われていますが、なぜそれが共分散ではないのか説明していませんか?リンクされたブログ投稿を読む?両者の違いを説明するのはとても良い仕事です。どの部分を理解できませんでしたか? * "Assignment Compatibility"は共分散ですが、すべての共分散が "Assignment Compatibility"ではないのですか? "*いいえ、それは明確な概念です。ただし、割り当ての互換性は共変関係で保持されていると言えるでしょう。 –

3

共変動は、サブタイプおよびジェネリックの相互作用に関連する。あなたのプログラムはジェネリックスを含まないので、共分散の例ではありません。

UV(例えば​​とV = Fruit)のサブタイプである場合、ジェネリック型G<T>G<U>G<V>のサブタイプである場合T共変であると言われます。たとえば、IEnumerable<Pear>IEnumerable<Fruit>のサブタイプです。梨を取って果物を取ることができます。

Gは(G<V>G<U>のサブタイプである)サブタイプ関係を逆転した場合、T反変であると言われます。例えば、Action<Fruit>Action<Pear>のサブタイプである:あなたが果物を置くことができる何かがで梨を置くために使用することができます

あなたの例では、ICarInterfaceCarでもないが、それはで共変することができタイプのパラメータを持つ

具体的には、C#では、タイプパラメータTの汎用タイプは、にoutとマークされている場合、共変です。 Tinとマークされている場合、Tに反変です。

+0

>> "共分散はサブタイプとジェネリックの相互作用に関連しています" C#1の配列共分散については、ジェネリックが存在しなかったので、 共分散を持つためには、一般的なコレクション/リストを持つ必要があるというあなたの回答をまとめるには?私の例は一般的なコレクション/リストを持たないので、共分散はありませんか? – Exocomp

+1

C#には当時のジェネリックがないため、特定の配列の場合はハードコードされていました。基本的にarray *はジェネリック型です: 'T []'の代わりに 'Array 'を読むことができます。 (実際の 'Array'クラスは一般的ではありません;これは非ジェネリックな' IList'と 'ArrayList'のように歴史的なものです)。ここでの配列共分散は' Pear [] 'が' Fruit [ '。これは 'IEnumerable 'の場合に似ています。 (配列の共分散は危険であることに注意してください。実は 'Pear []'である 'Fruit 'に' Orange'を置くことができます)。 – Ruud

+0

また、共分散と反差異は一般的なコレクションに限定されません。例えば、 'Func 'は 'TResult'では共変で、' T'では反変です。共分散および反分散は、型パラメータの特性である。あなたの例に型パラメータがないので、共変できないものはありません。 – Ruud