Ковариантность и Контравариантность заключают в C# 4.0

Когда мы определяем наши интерфейсы в C# 4.0, нам разрешают отметить каждый из универсальных параметров как in или out. Если бы мы пытаемся установить универсальный параметр как, и это привело бы к проблеме, компилятор повышает ошибку, не позволяя нам сделать это.

Вопрос:

Если компилятор имеет способы вывести то, что является допустимым использованием для обоих covariance (out) и contravariance(in), почему мы должны отметить интерфейсы как таковые? Разве не было бы достаточно просто позволить нам определить интерфейсы, как мы всегда делали, и когда мы пытались использовать их в нашем клиентском коде, повысить ошибку, если мы пытались использовать их небезопасным способом?

Пример:

interface MyInterface<out T> {
    T abracadabra();
}
//works OK

interface MyInterface2<in T> {
    T abracadabra();
}
//compiler raises an error.
//This makes me think that the compiler is cappable 
//of understanding what situations might generate 
//run-time problems and then prohibits them.

Кроме того,

разве это не то, что Java делает в той же ситуации? Из того, что я вспоминаю, Вы просто делаете что-то как

IMyInterface<? extends whatever> myInterface; //covariance
IMyInterface<? super whatever> myInterface2; //contravariance

Или я смешиваю вещи?

Спасибо

8
задан devoured elysium 28 April 2010 в 22:33
поделиться

2 ответа

Если у компилятора есть способы определить, что является допустимым использованием ковариации (out) и контравариации (in), зачем нам помечать интерфейсы как таковые?

Я не совсем уверен, что понимаю вопрос. Мне кажется, вы спрашиваете о двух вещах.

1) Может ли компилятор вывести аннотации дисперсии?

и

2) Почему C# не поддерживает дисперсию места вызова, как это делает Java?

Ответ на первый:

interface IRezrov<V, W> 
{
    IRezrov<V, W> Rezrov(IRezrov<W, V> x);
}

Я приглашаю вас попытаться вывести все законные возможные аннотации дисперсии для V и W. Вас может ждать сюрприз.

Если вы не можете найти уникальную наилучшую аннотацию дисперсии для этого метода, почему вы думаете, что компилятор сможет?

Больше причин здесь:

http://blogs.msdn.com/ericlippert/archive/2007/10/29/covariance-and-contravariance-in-c-part-seven-why-do-we-need-a-syntax-at-all.aspx

В целом: ваш вопрос указывает на ошибочность рассуждений. Возможность дешево проверить правильность решения логически не означает, что существует дешевый способ найти правильное решение. Например, компьютер может легко проверить, является ли p * q == r истинным или ложным для двух тысячезначных простых чисел p и q. Это не означает, что легко взять r и найти p и q такие, что равенство будет выполнено. Компилятор может легко проверить, является ли аннотация дисперсии правильной или неправильной; это не означает, что он может найти правильную аннотацию дисперсии среди потенциально миллиардов возможных аннотаций.

Ответ на второй вопрос: C# - это не Java.

8
ответ дан 5 December 2019 в 20:14
поделиться

Хорошо, вот ответ на мой вопрос (из ответа Эрика) : http://blogs.msdn.com/ericlippert/archive/2007/10/29/covariance-and-contravariance-in-c-part-seven-why-do-we-need-a-syntax-at-all.aspx

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

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

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

0
ответ дан 5 December 2019 в 20:14
поделиться