Понимание ковариантности и контравариантности в C # 4.0 - PullRequest
17 голосов
/ 12 ноября 2009

Я смотрел видео об этом на 9 канале, но на самом деле я не очень понимал это.

Может кто-нибудь дать мне простой пример, который легко понять? После этого, может быть, как это будет использоваться на практике?

Ответы [ 5 ]

8 голосов
/ 12 ноября 2009

Возможно, вы захотите взглянуть на этот блог, он проделывает фантастическую работу по его объяснению, но я думаю, что потребуется больше примеров, чтобы прояснить его для людей, поскольку это становится очень трудной для понимания областью, но приведенная ниже цитата из статьи хорошо подводит итог.

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

«ковариация и контравариантность» означает что теперь вы можете передать неточный общий типы, когда это безопасно сделать, так же, как вы можете передать неточные типы аргументов когда это безопасно.

7 голосов
/ 17 февраля 2014

A Tiger - это Animal, поэтому он может делать все, что может Animal. Если у меня есть метод, который запрашивает Animal, я также могу передать Tiger.

Ковариация - Передача аргумента более определенного типа

Это направление, с которым вы наиболее знакомы. Я могу передать IEnumerable<Tiger> везде, где ожидается IEnumerable<Animal>.


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

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

Contravariance - Передача аргумента более общего типа.

"Против" подразумевает, что это идет "против" нормального потока преобразования. Это хитрее, потому что кажется нелогичным, пока вы не увидите его в действии.

Скажем, у меня есть функция, которая ожидает IComparer<Tiger> и двух тигров для сравнения. Contravariance говорит, что я также могу передать более общий 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>.

3 голосов
/ 11 декабря 2009

Эрик Липперт дал очень хорошее объяснение в недавнем сообщении в блоге

1 голос
/ 12 ноября 2009

Следующая статья посвящена совместной и противоречивой оценке делегатов: http://msdn.microsoft.com/en-us/library/ms173174.aspx.

Возможно, это полезно для вас, даже если вы еще не являетесь делегатом. Я понял, что это довольно легко понять.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...