了解C# 4.0中的协变和逆变

17

我在Channel 9上看了一段关于IT技术的视频,但我并没有很好地理解它。

请问有人能够给我一个简单易懂的例子吗?之后或许能够说明这在实践中如何应用?


2
http://channel9.msdn.com/ - 这是一个关于微软开发框架和更多内容的视频集合 :) - cwap
这个链接 https://dev59.com/VHNA5IYBdhLWcg3wIqPr 可以回答你很多关于它的问题(还可以看看Jon Skeet提供的Eric Lippert博客链接)。 - Matt Ball
是的,就像播客一样,有一些与Anders相关的非常好的C#视频等。 - Joan Venge
5个回答

9

你可能想看一下这篇博客,他非常好地解释了这个问题,但我认为需要更多的例子来帮助人们理解,因为这涉及到一个非常难以理解的领域,但是文章中下面的引用很好地总结了这个问题。

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

“协变性和逆变性”意味着当安全时,您现在可以传递不精确的通用类型,就像在安全时可以传递不精确的参数类型一样。

8

Tiger是一种动物,因此它可以做任何动物能做的事情。如果我有一个要求动物的方法,我也可以传入一个Tiger

协变性 - 传递更具体的类型参数

这是您最熟悉的方向。我可以将IEnumerable<Tiger>传递到任何期望IEnumerable<Animal>的地方。


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

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

逆变性 - 传递更一般的类型参数。'contra' 意味着这与正常的转换流程相反。这个比较棘手,因为它似乎是违反直觉的,除非你亲自实践过。 假设我有一个期望一个 IComparer 和两只老虎进行比较的函数。逆变性表明我也可以传递更一般的 IComparer,因为它也可以比较两只老虎(因为老虎是动物)。它以一种更一般的方式进行比较,但这仍然是类型安全的。
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());

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

3

在最近一篇博客文章中,Eric Lippert提供了一个非常好的解释。


1

1

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