Зачем нам нужны новые ключевые слова для ковариации и контравариантности в C #? - PullRequest
17 голосов
/ 06 ноября 2008

Может кто-нибудь объяснить, почему необходимо добавить параметр out или in, чтобы указать, что универсальный тип является вариантом Co или Contra в C # 4.0?

Я пытался понять, почему это важно и почему компилятор не может просто понять это ...

Спасибо

Josh

Ответы [ 5 ]

18 голосов
/ 06 ноября 2008

Эрик Липперт, который работает над языком, опубликовал серию сообщений на MSDN, которые должны помочь прояснить проблемы: http://blogs.msdn.com/ericlippert/archive/tags/Covariance+and+Contravariance/default.aspx

При чтении статей, показанных по этой ссылке, начните снизу и продолжайте.

В конце концов вы получите # 7 (зачем нам вообще нужен синтаксис?) .

7 голосов
/ 06 ноября 2008

Нам на самом деле не нужно их, больше, чем нам нужно abstract на классах или оба out и ref. Они существуют только для того, чтобы мы, как программисты, могли предельно ясно понять наши намерения, чтобы программист по техническому обслуживанию знал, что мы делаем, а компилятор мог убедиться, что мы все делаем правильно.

6 голосов
/ 06 ноября 2008

Ну, главная проблема в том, что если у вас есть иерархия классов, например:

   class Foo { .. } 

   class Bar : Foo { .. } 

И у вас есть IEnumerator<Bar>, вы не можете использовать его как IEnumerator<Foo>, хотя это было бы совершенно безопасно. В 3.5 это вызывает большое количество болезненных вращений. Эта операция всегда была бы безопасной, но она отклонена системой типов, потому что она не знает о ковариантном использовании параметра универсального типа. IEnumerator<Bar> может вернуть только Bar, а каждое Bar - это Foo.

Аналогично, если у вас есть IEqualityComparer<Foo>, его можно использовать для сравнения любой пары объектов типа Foo, даже если один или оба являются Bar, но его нельзя преобразовать в IEqualityComparer<Bar>, потому что он не знает о контравариантном использовании универсального параметра типа. IEqualityComparer<Foo> потребляет только объекты типа Foo, и каждый Bar является Foo.

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

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

1 голос
/ 06 ноября 2008

Джон и Джоэл оба дали довольно полный ответ на этот вопрос, но суть в том, что они не так уж и необходимы необходимы компилятором, а скорее помогают гарантировать безопасность реализации путем явного указания дисперсия параметра. Это очень похоже на требование ключевого слова out или ref как на вызывающем сайте, так и на сайте объявления.

1 голос
/ 06 ноября 2008

Ключевые слова in и out были ключевыми словами начиная с C # 1.0 и использовались в контексте in - и out - параметров методов.

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

...