Подтвердить что ты не робот

Понимание ковариации и контравариантности в С# 4.0

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

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

4b9b3361

Ответ 1

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

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

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

Ответ 2

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

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

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


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

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

Контравариантность. Передача более общего аргумента типа.

"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>.

Ответ 3

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

Ответ 4

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

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

Ответ 5

Документы MSDN для С# 4.0 (и VB) находятся здесь: Ковариация и контравариантность

Если вас интересуют конкретные примеры, они находятся здесь: