理解C#4.0中的协方差和逆变

时间:2009-11-12 19:52:40

标签: c# .net covariance contravariance

我在第9频道观看了一段关于它的视频,但我对此并不是很了解。

有人可以给我一个关于这些容易理解的简单例子吗?那之后可能会如何在实践中使用它?

5 个答案:

答案 0 :(得分:8)

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

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

  

“协方差和逆变”是指   你现在可以传递不精确的泛型   如果这样做是安全的,就像这样   你可以传递不精确的参数类型   什么时候这样做是安全的。

答案 1 :(得分:7)

TigerAnimal,因此它可以执行Animal可以执行的任何操作。如果我有一个要求Animal的方法,我也可以传入Tiger

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

这是您最熟悉的方向。我可以在需要IEnumerable<Tiger>的任何地方传递IEnumerable<Animal>


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

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

Contravariance - 传递更一般的类型参数。

'contra'意味着这与正常的转换流程“相对”。这个比较棘手,因为它看起来反直觉,直到你看到它在行动。

假设我有一个功能,需要比较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());

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

答案 2 :(得分:3)

Eric Lippert在最近的blog post

中提出了一个非常好的解释

答案 3 :(得分:1)

以下文章涉及与代表的共同和逆转:http://msdn.microsoft.com/en-us/library/ms173174.aspx

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

答案 4 :(得分:1)