.NET:协变和逆变

6

可能是重复问题:
协变与逆变的区别

我正在尝试理解什么是协变和逆变,以及两者之间的区别。我已经查看了此链接,目前我已经理解以下内容:

协变是将派生成员分配给基础成员的过程。例如:

IEnumerable<Derived> d = new List<Derived>();
IEnumerable<Base> b = d;

我甚至不确定我上面的猜测是否正确。基本上,我正在寻找一个人用最简单的术语为我解释两者之间的区别,以便我能够理解。

我也知道有类似的讨论话题,但大多数答案并不是我想要的描述。

1个回答

0

对于我们的内部培训,我使用了精彩的书籍《Smalltalk, Objects and Design (Chamond Liu)》,并重新表述了以下示例。-希望这有所帮助...

“一致性”是什么意思? 设计类型安全的类型层次结构,具有高度可替代的类型。获得这种一致性的关键是基于子类型的一致性。 (我们将在此处高层次地讨论Liskov替换原则(LSP)。)

协变: 假设鸟类以静态类型“一致地”下蛋: 如果Bird类型下蛋,则Bird的子类型是否会下一个Egg子类型? 例如,Duck类型下一个DuckEgg,那么就满足了一致性。 为什么这是一致的?因为在这样的表达式中: Egg anEgg = aBird.Lay(); 引用aBird可以合法地被Bird或Duck实例替换。 我们说返回类型对定义Lay()的类型是协变的。 子类型的重写可能会返回更专业的类型。 => “它们提供更多。”

逆变性: 假设钢琴家可以使用静态类型“一致地”演奏钢琴: 如果钢琴家弹奏钢琴,她能够弹奏大钢琴吗? 难道不应该是大师级钢琴家弹奏大钢琴吗?(请注意,这里有一个转折!)这是不一致的!因为在这样的表达式中: aPiano.Play(aPianist); aPiano 不能被 Piano 或 GrandPiano 实例合法替换!大钢琴只能由钢琴大师演奏,钢琴家太普通了! 大钢琴必须能够被更一般的类型演奏,这样才能保持一致。 我们说参数类型反变为定义 Play() 的类型。 子类型的覆盖可能接受更广泛的类型。 => “它们需要更少。”


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接