好的,让我们A
用Fish
, IA
with IAnimal
, B
withAquarium
和IB<T>
with 替换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 被键入为可以包含任何动物的容器。但是您只能将鱼放入水族馆。由于您可以在 an 上合法执行的操作与您可以在 an 上执行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/