Understanding Covariance and Contravariance in C# 4.0

旧巷老猫 提交于 2019-11-26 18:09:23

问题


I watched a video about it on Channel 9 but I didn't really understand it much.

Can someone please give me a simple example about these that's easy to understand? After that maybe how it would be used in practice?


回答1:


You may want to look at this blog, he does a fantastic job of explaining it, but I think it will take more examples to clear it up for people, as this gets into a very hard-to-understand area, but, the quote below from the article sums it up well.

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

"covariance and contravariance" means that you can now pass inexact generic types when it's safe to do so, just as you can pass inexact argument types when it's safe to do so.




回答2:


A Tiger IS an Animal so it can do anything an Animal can do. If I have a method that asks for an Animal I can also pass in a Tiger.

Covariance - Passing a more specific type argument

This is the direction you are most familiar with. I can pass an IEnumerable<Tiger> anywhere that expects an IEnumerable<Animal>.


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

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

Contravariance - Passing a more general type argument.

The 'contra' implies that this goes 'against' the normal conversion flow . This one is trickier because it seem's counter-intuitive until you see it in action.

Say I have a function which expects an IComparer<Tiger> and two tigers to be compared. Contravariance says I can also pass in the more general IComparer<Animal> because it can also compare two tigers (since a Tiger IS an animal). It compares them in a more general way, but this is still type safe.


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());

Note that this also works with delegates. I can pass an Action<Animal> into a function that expects an Action<Tiger> because Tiger objects can also be passed safely to the Action<Animal> delegate.




回答3:


Eric Lippert came up with a very good explanation in a recent blog post




回答4:


The following article deals with co- and contravariance with delegates: http://msdn.microsoft.com/en-us/library/ms173174.aspx.

Perhaps it is useful to you, even if you're not into delegates yet. I found it to be quite easy to understand.




回答5:


MSDN docs for C# 4.0 (and VB) are here: Covariance and Contravariance

If you are interested in concrete examples, they are here:

  • Using Variance in Interfaces for Generic Collections

  • Using Variance in Delegates

  • Using Variance for Func and Action Generic Delegates



来源:https://stackoverflow.com/questions/1724919/understanding-covariance-and-contravariance-in-c-sharp-4-0

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!