2012-04-27 13 views
14

I持って、次のクラス/インタフェース:私は次のエラーを取得しています実装ネストされた汎用的なインタフェース

IB<IA> foo = new B(); 

:私は、次のコードを使用して新しいインスタンスを作成しよう

// Model 
public class A : IA { } 
// ModelLogic 
public class B : IB<A> { } 

// Model Interface 
public interface IA { } 
// ModelLogic Interface 
public interface IB<T> where T : IA { } 

Cannot implicitly convert type 'B' to 'IB<IA>'. An explicit conversion exists (are you missing a cast?) 

これはなぜ不可能なのか説明してもらえますか?

+0

使用しているC#のバージョンは何ですか? – Oded

+3

[共分散とContravarianceのFAQ](http://blogs.msdn.com/b/csharpfaq/archive/2010/02/16/covariance-and-contravariance-faq.aspx)と[このブログシリーズ](http: /blogs.msdn.com/b/ericlippert/archive/tags/covariance+and+contravariance/)by Eric Lippert – Oded

答えて

41

OK、のはIContainer<T>FishAIAIAnimalと、BAquariumと、そしてIB<T>を交換しましょう。そして、我々はIContainer<T>にメンバーを追加し、IAnimalの第2の実施う:

// Model 
public class Fish : IAnimal { } 
public class Tiger : IAnimal { } 
// ModelLogic 
public class Aquarium : IContainer<Fish> 
{ 
    public Fish Contents { get; set; } 
} 

// Model Interface 
public interface IAnimal { } 
// ModelLogic Interface 
public interface IContainer<T> where T : IAnimal 
{ 
    T Contents { get; set; } 
} 

IContainer<IAnimal> foo = new Aquarium(); // Why is this illegal? 
foo.Contents = new Tiger(); // Because this is legal! 

あなたはFOOにタイガーを置くことができます - fooが任意の動物を含むことができ、コンテナとして入力されます。しかし、あなたは水族館に魚を入れることができます。 Aquariumで法的に実行できる操作は、IContainer<IAnimal>で実行できる操作とは異なり、とは異なるため、の操作は実行できません。

したい機能が汎用インタフェース共分散と呼ばれ、はC#4でサポートされているですが、あなたがあなたの水槽の中に虎を置くことは決してありませんコンパイラに証明する必要があります。やりたいことです:

// Model 
public class A : IA { } 
// ModelLogic 
public class B : IB<A> { } 

// Model Interface 
public interface IA { } 
// ModelLogic Interface 
public interface IB<out T> where T : IA { } 

IB上の共分散アノテーションを注意してください。このoutは、Tは入力としてではなく、の出力としてのみ使用できることを意味します。 Tが出力にすぎない場合、誰かが魚のタンクに虎を入れる方法はありません。なぜなら、可能なプロパティやメソッドがないからです。

私はその機能をC#に追加している間に、いくつかのブログ記事を書きました。あなたが機能に入った設計上の考慮事項に興味がある場合は、以下を参照してください

http://blogs.msdn.com/b/ericlippert/archive/tags/covariance+and+contravariance/

+0

無効な分散:タイプパラメータ 'T'は、 'xx.IContainer .Contents'で不変に有効である必要があります。 'T'は共変数である。 \tこのエラーが発生しています。私は共変なものに新しいです。エラーはどういう意味ですか? – Sandeep

+3

@Sandeep:あなたは、出力位置でのみ使用すると言ったとき、何とか入力位置でTを使用しています。 'Contents'はセッターを持つプロパティですか?そうであれば、明らかにTが入力位置で使用されているため、Tでインタフェースを共変えることはできません。 –

+0

ありがとうございます。それがそれを解決しました。 – Sandeep

1

をあなたのコードを修正するには、ちょうどそれは簡単ではありません

public interface IB<out T> where T : IA { } 
+0

awww、エリック私にそれを打つ:) – CodingWithSpike

0

public interface IB<T> where T : IA { } 

を変更空のインターフェイスがいつあるかを確認してください。

public interface IB<T> where T : IA 
{ 
    void M(T t); 
} 

そして、ここではBの実装です:あなたはインタフェースIB内の1つの方法Mを持って考えてみましょう

public class B : IB<A> 
{ 
    public void M(A t) 
    { 
     // only object of type A accepted 
    } 
} 

その後、あなたはまた、IAを実装するオブジェクトのCを、持っている:

public class C : IA { } 

ので、あなたのコードが可能であれば、電話することができます:

IB<IA> foo = new B(); 
foo.M(new C()); 

クラスBはタイプAのオブジェクトだけを受け入れるという問題があります。エラー!

関連する問題