Понимание ковариации и контравариантности в С# 4.0
Я смотрел видео об этом на 9-м канале, но я этого не очень-то понял.
Может кто-нибудь, пожалуйста, дайте мне простой пример об этом, который легко понять? После этого возможно, как это будет использоваться на практике?
Ответы
Ответ 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) находятся здесь: Ковариация и контравариантность
Если вас интересуют конкретные примеры, они находятся здесь: