2016-09-20 11 views
0

理由は、多くの場合、このような実施例により例示されています。汎用共分散時の安全性チェックをコンパイル

public class Fruit 
{ 
} 

public class Apple : Fruit 
{ 
} 

public class Banana : Fruit 
{ 
} 

次が許可されています:

public void Permitted() 
{ 
    IEnumerable<Fruit> bananas = new List<Banana> 
    { 
     new Banana(), 
     new Banana(), 
     new Banana(), 
    }; 

    foreach (Fruit banana in bananas) 
    { 
     // This is all good, because a banana "is a" fruit and 
     // we can treat it as such. 
    } 
} 

次が禁止されています

public void Disallowed() 
{ 
    // Compiler rejects this! 
    List<Fruit> bananas = new List<Banana> 
    { 
     new Banana(), 
     new Banana(), 
     new Banana(), 
    }; 

    // ...Otherwise we can add an apple to a list containing bananas 
    bananas.Add(new Apple()); 
} 

しかし、我々はまだ実行してこれを達成することができ、以下のクラスを考えると

以下:

public void Loophole() 
{ 
    // Compiler is happy again 
    IEnumerable<Fruit> bananas = new List<Banana> 
    { 
     new Banana(), 
     new Banana(), 
     new Banana(), 
    }; 

    // ...And now we can add an apple to a list of bananas 
    bananas.ToList().Add(new Apple()); 
} 

そしてもちろん、私たちはこれを行うことができます:

public void AlsoAllowed() 
{ 
    var fruit = new List<Fruit>(); 
    fruit.Add(new Apple()); 
    fruit.Add(new Banana()); 
} 

List<T>が共変されていないため、共通の引数は、(私の理解あたりとして)そうすることが、私たちはに任意のベースオブジェクトを追加できるようになるということです派生オブジェクトを含むコレクション。たぶん、これは単純化すぎですが、上記の例がやっていることではありませんか?

答えて

4

bananas.ToList().Add(new Apple())を実行すると、bananas.ToList()List<Fruit>を作成します。これは任意のタイプの果物を含むことができるリストタイプです。 new Apple()がそのリストに追加できるという事実は理にかなっています。

bananasは、タイプがList<Banana>であり、バナナのみを含むことができるリストタイプです。このリストにnew Apple()を追加する方法はありません。あなたの例はではありませんはこのリストにnew Apple()を追加してください。あなたの例は、より寛容なリストを作成し、追加しますが、元のリストは変更しません。

+0

2番目の例では、 'Apple'sと' Banana'sを 'fruit'に追加するだけで間違ったことはありません。これは型付きではなく' List 'としてインスタンス化されています。 –

+0

非常に明白な今あなたがそれを言及する - ありがとう! – LeopardSkinPillBoxHat