На C#: это дисперсия (ковариация / Контрвариантность) другое слово полиморфизм?


Я пытаюсь выяснить точное значение слов Covariance и Contravariance из нескольких статей в интернете и вопросов о StackOverflow, и из того, что я могу понять, это только другое слово для полиморфизма.

Прав ли я с приведенным выше утверждением? Или я что-то не так понял ?

5 37

5 ответов:

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

Например, при нормальном полиморфизме вы можете рассматривать любую ссылку на A Banana как ссылку на A Fruit - но это не означает, что вы можете заменить Fruit каждый раз вы видите тип Banana. Например, a List<Banana> нельзя рассматривать как a List<Fruit> потому что list.Add(new Apple()) справедливо для List<Fruit>, но не для List<Banana>. Ковариация

Позволяет заменить "больший" (менее специфичный) тип в API, где исходный типиспользуется только в позиции "выход" (например, в качестве возвращаемого значения). Контравариантность позволяет заменить" меньший " (более специфичный) тип в API, где исходный тип используется только в позиции "вход".

Трудно вдаваться во все детали в одном посте SO (хотя, надеюсь кто-то другой справится лучше, чем это!). У Эрика Липперта есть отличнаясерия записей в блоге Об этом.

Спасибо за все выкрики, ребята.

Ответы Джона и Расмуса прекрасны, я бы просто добавил краткое техническое Примечание. Говоря небрежно и неофициально, да, люди используют "ковариацию" и "контравариацию" для обозначения определенного вида полиморфизма. Это своего рода полиморфизм, когда вы относитесь к последовательности пауков, как если бы это была последовательность животных.

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

Во-первых, я бы отметил, что есть два возможных вида полиморфизма в C#, о которых вы, возможно, говорите, и важно не путать их. Первый тип традиционно называют "ad hoc полиморфизмом", и это полиморфизм, в котором у вас есть метод M (животное x), и вы передаете ему пауков, жирафов и валлаби, а также метод равномерно обрабатывает свои переданные аргументы таким же образом, используя общие свойства, гарантированные базовым классом Animal. Второй тип традиционно называют "параметрическим полиморфизмом", или "родовым полиморфизмом". Это возможность сделать общий метод M<T>(T t) , а затем иметь кучу кода в методе, который снова обрабатывает аргумент равномерно, основываясь на общих чертах, гарантированных ограничениями на T. Я думаю, что вы говорите о первом типе полиморфизма. Но моя точка зрения заключается лишь в том, что мы можем определить полиморфизм как способность языка программирования рассматривать различные вещи одинаково, основываясь на известной общности. (например, известный базовый тип или известный реализованный интерфейс.) Ковариация и контравариантность-это способность языка программирования использовать в своих интересах общности между универсальными типами, выведенные из известных общностей их аргументов типа.

Вы можете думать о Ко-и контравариантности как о продвинутой форме полиморфизма. Вы не только можете использовать дочерний класс, как если бы он был родительским классом, с Ко-и контравариантностью, полиморфизм распространяется на классы, которые относятся к полиморфным классам.

Представьте себе два класса:

public class Pet { /*...*/ }
public class Cat:Pet { /*...*/ }

Полиморфизм может использовать Cat как Pet:

void Feed(Pet pet) { /* ... */ }

Cat cat = ...
Feed(cat);

Ко-и контравариантность используется, чтобы говорить о возможности использовать ICollection<Cat> Как ICollection<Pet> (ковариация):

void FeedAll(ICollection<Pet> pets) { /* ... */ }

List<Cat> cats = ...
FeedAll(cats);

Или использовать Action<Pet> как Action<Cat> (контравариантность):

Action<Pet> GetFeeder() { /* ... */ }

Action<Cat> feeder = GetFeeder();
Эрик Липперт написал об этом замечательную серию блогов, когда они впервые разрабатывали эту функцию. Первая часть-это здесь .

Я нашел эту коллекцию:

Ковариация и контравариантность в C#, Часть первая

Ковариация и контравариантность в C#, Часть вторая: ковариация массива

Ковариация и контравариантность в C#, Часть третья: дисперсия преобразования групп членов

Ковариация и контравариантность в C#, Часть четвертая: реальная дисперсия делегата

Ковариация и контравариантность в C#, Часть пятая: функции высшего порядка вредят моему Мозг

Ковариация и контравариантность в C#, Часть шестая: дисперсия интерфейса

Ковариация и контравариантность в C# Часть седьмая: зачем вообще нужен синтаксис?

Ковариация и контравариантность в C#, часть Восьмая: синтаксические параметры

Ковариация и контравариантность в C#, Часть девятая: разрушающие изменения

Ковариация и контравариантность в C#, часть Десятая: работа с неоднозначностью

Ковариация и Контравариантность, часть Одиннадцатая: до бесконечности, но не дальше

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