2012-02-08 32 views
0

状況を再現するために私の最高の試みです。ジェネリックコレクションの衝突

public interface IFoo 
{ 

} 

public class Foo : IFoo { } 

public class Bar : IFoo { } 

public class CollectionOf<T> : List<IFoo> 
{ 

} 

public class Bars : CollectionOf<Bar> 
{ 

} 

public class Test 
{ 
    public void Test() 
    { 
     CollectionOf<IFoo> bars = new Bars(); 
    } 
} 

コンパイラがインスタンス化に不満を持ちます。バーはIFoosのコレクションです。これらは共分散/反分散問題の1つですか?

+0

ありがとう@EdS。修正は何ですか? – Matthew

+0

共分散/反変分のサポートが必要な場合は、 'CollectionOf'がコレクションを読み込むか、コレクションに追加するかを知る必要があります。共分散または反共分散をサポートすることはできません。 – Lukazoid

答えて

1

修正プログラムがある場合は、それが機能していないことが原因です。私はあなたの例を2つの方法でコンパイルすることができます。IEnumerableを使用するか、CollectionOfをoutジェネリック修飾子を持つインターフェイスとして定義します。どちらかがあなたのための修正であるかどうかわかりません:

public interface IFoo { } 

public class Foo : IFoo { } 

public class Bar : IFoo { } 

public interface CollectionOf<out T> : IEnumerable<IFoo> { } 

public class Bars : CollectionOf<Bar> { } 

public class Test 
{ 
    public void Test() 
    { 
     IEnumerable<IFoo> bars1 = new Bars(); 
     CollectionOf<IFoo> bars2 = new Bars(); 
    } 
} 
+0

私はこれが私が探しているものだと信じています。私はCollectionOfから削除する必要がありますので、必要なものがあります。 – Matthew

2

はいです。

これが許可されている場合、IFooインターフェイスを実装していればそのコレクションに任意のオブジェクトを配置できますが、それはコレクションにとって安全ではありません。

私が説明してみましょう:この時点で

var b = new Bars(); 
CollectionOf<IFoo> bars = b; 
bars.Add(Dummy); // implements IFoo, but does not descend from Bar 

bは何が含まれていますか?タイプDummyのオブジェクトですか?それは悪いので、最初は許されません。

+0

あなたのファストフィンガーをくそっ... –

+0

ありがとう、それ以来完璧です。 はどこに遊びに来ていますか? – Matthew

+1

''または_covariance_は、クラス 'Foo 'がその要素をアップキャストできることを意味します。たとえば、 'Foo myFoo = new Foo ();'などです。この状況では、 'T'は戻り値の型にしか使えません(したがって、out)。詳細については、こちらの[リンク](http://msdn.microsoft.com/en-us/library/ee207183.aspx)を参照してください。 – Lukazoid

4

はい。

もう一度考えてみましょう。 barsは、IFooを実装するすべてのタイプのオブジェクトを合法的に保持できる必要があります。ただし、タイプBarsのオブジェクトは、Barのオブジェクトを保持するのみとすることができます。

あなたのコードを使用すると、これは許されますが、明らかに間違っています。

CollectionOf<IFoo> bars = new Bars(); 
bars.Add(new Foo()); // Uh oh! 

これは、ジェネリック医薬品によってあなたに与えられた型安全性を効果的に損なうことになります。

+0

バーをそのコレクションに入れることを約束すればどうなりますか? またははすべてについてですか? – Matthew

+0

コレクションに 'Bar'だけを入れたいのであれば、' CollectionOf bars = new Bars(); 'を使うのはどうですか? – Lukazoid

+0

@Matthew:いいえ、間違った動作を許可していません。インタフェースを介してのみ作業しない限り、 'Foo'を' Bar'のコレクションに追加することはできません。これはC++ではありません。ジェネリックは強く型付けされています。フォームを確実にする状況では、意味がなく、標準で定義されていない動作が発生します。 –