С#:Является ли дисперсия (ковариация/контравариантность) другим словом для обозначения полиморфизма?

StackOverflow https://stackoverflow.com/questions/1078423

Вопрос

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

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

Это было полезно?

Решение

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

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

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

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

Другие советы

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

Ответы Джона и Расмуса хороши, я бы просто добавил небольшое техническое примечание.

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

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

Во-первых, я хотел бы отметить, что в C# есть два возможных типа полиморфизма, о которых вы, возможно, говорите, и важно их не путать.

Первый тип традиционно называется «специальным полиморфизмом», и это полиморфизм, при котором у вас есть метод M(Animal 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#, часть десятая:Как справиться с двусмысленностью

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top