では、 、、 、 、に置き換えてみAましょう。そして、メンバーを に追加し、 の 2 番目の実装を追加します。FishIAIAnimalBAquariumIB<T>IContainer<T>IContainer<T>IAnimal
// 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!
Tiger を 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を意味します。が出力のみの場合、「入れる」プロパティまたはメソッドが存在しないため、だれかがトラをその水槽に入れる方法はありません。TT
その機能を C# に追加している間、私はいくつかのブログ記事を書きました。この機能に組み込まれた設計上の考慮事項に興味がある場合は、以下を参照してください。
http://blogs.msdn.com/b/ericlippert/archive/tags/covariance+and+contravariance/