Когда мы определяем наши интерфейсы в 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
Или я смешиваю вещи?
Спасибо
Если у компилятора есть способы определить, что является допустимым использованием ковариации (out) и контравариации (in), зачем нам помечать интерфейсы как таковые?
Я не совсем уверен, что понимаю вопрос. Мне кажется, вы спрашиваете о двух вещах.
1) Может ли компилятор вывести аннотации дисперсии?
и
2) Почему C# не поддерживает дисперсию места вызова, как это делает Java?
Ответ на первый:
interface IRezrov<V, W>
{
IRezrov<V, W> Rezrov(IRezrov<W, V> x);
}
Я приглашаю вас попытаться вывести все законные возможные аннотации дисперсии для V и W. Вас может ждать сюрприз.
Если вы не можете найти уникальную наилучшую аннотацию дисперсии для этого метода, почему вы думаете, что компилятор сможет?
Больше причин здесь:
В целом: ваш вопрос указывает на ошибочность рассуждений. Возможность дешево проверить правильность решения логически не означает, что существует дешевый способ найти правильное решение. Например, компьютер может легко проверить, является ли p * q == r истинным или ложным для двух тысячезначных простых чисел p и q. Это не означает, что легко взять r и найти p и q такие, что равенство будет выполнено. Компилятор может легко проверить, является ли аннотация дисперсии правильной или неправильной; это не означает, что он может найти правильную аннотацию дисперсии среди потенциально миллиардов возможных аннотаций.
Ответ на второй вопрос: C# - это не Java.
Хорошо, вот ответ на мой вопрос (из ответа Эрика) : 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
Во-первых, мне кажется, что дисперсия должна быть чем-то, что вы намеренно разрабатывается в вашем интерфейс или делегат. Заставлять его просто начать происходить без какого-либо контроля со стороны пользователя, противоречит этой цели, а также может внести разрушающие изменения. (Подробнее об этом в следующем посте!)
Делать это автоматически также означает, что по мере того, как процесс разработки продолжается и методы добавляются к интерфейсам, то дисперсия интерфейса может измениться неожиданно. Это может внести неожиданные и далеко идущие изменения в других частях программы.
Я решил прямо изложить это здесь, потому что, хотя в его ссылке есть ответ на мой вопрос, в самом посте его нет.