17

我在第 9 频道观看了有关它的视频,但我并没有真正理解它。

有人可以给我一个简单易懂的例子吗?在那之后,它可能会如何在实践中使用?

4

5 回答 5

9

你可能想看看这个博客,他解释得很好,但我认为需要更多的例子来为人们澄清它,因为这进入了一个非常难以理解的领域,但是,引用下面的文章总结得很好。

http://hestia.typepad.com/flatlander/2008/12/c-covariance-and-contravariance-by-example.html

“协变和逆变”意味着您现在可以在安全的情况下传递不精确的泛型类型,就像在安全的情况下可以传递不精确的参数类型一样。

于 2009-11-12T19:58:14.540 回答
7

A TigerIS anAnimal所以它可以做任何Animal可以做的事情。如果我有一个要求 a 的方法,Animal我也可以传入 a Tiger

协方差- 传递更具体的类型参数

这是你最熟悉的方向。我可以通过IEnumerable<Tiger>任何需要IEnumerable<Animal>.


static void ListAnimals(IEnumerable<Animal> animals)
{
}

List<Tiger> tigers = new List<Tiger>();
ListAnimals(tigers);

逆变- 传递更通用的类型参数。

“对立”意味着这与正常的转换流程“背道而驰”。这个比较棘手,因为在你看到它之前它似乎是反直觉的。

假设我有一个函数需要IComparer<Tiger>比较一只和两只老虎。逆变说我也可以传递更一般的IComparer<Animal>,因为它也可以比较两只老虎(因为老虎是动物)。它以更一般的方式比较它们,但这仍然是类型安全的。


static void CompareTigers(IComparer<Tiger> comparer, Tiger tiger1, Tiger tiger2)
{
    comparer.Compare(tiger1, tiger2);
}

// normal - a tiger comparer can compare two tigers
IComparer<Tiger> tigerComparer = null;
CompareTigers(tigerComparer, new Tiger(), new Tiger());

// contravariance - an animal comparer can ALSO compare two tigers
IComparer<Animal> animalComparer = null;
CompareTigers(animalComparer, new Tiger(), new Tiger());

请注意,这也适用于代表。我可以将 an 传递给Action<Animal>一个期望 an 的函数,Action<Tiger>因为Tiger对象也可以安全地传递给Action<Animal>委托。

于 2014-02-17T07:29:08.593 回答
3

Eric Lippert 在最近的一篇博文中提出了一个很好的解释

于 2009-12-11T01:13:41.817 回答
1

以下文章处理与代表的协变和逆变:http: //msdn.microsoft.com/en-us/library/ms173174.aspx

也许它对你有用,即使你还没有进入代理。我发现它很容易理解。

于 2009-11-12T20:01:39.490 回答
1

C# 4.0(和 VB)的 MSDN 文档在这里:协方差和逆变

如果您对具体示例感兴趣,它们在这里:

于 2009-12-11T01:07:38.253 回答