Почему C # (4.0) не допускает ко-и контравариантности в типовых классах? - PullRequest
22 голосов
/ 30 марта 2010

Какова реальная причина такого ограничения? Это просто работа, которую нужно было сделать? Это концептуально сложно? Это невозможно?

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

Причина этого вопроса в том, что я пишу статью о поддержке отклонений в C # 4 и чувствую, что должен объяснить, почему она ограничена делегатами и интерфейсами. Просто чтобы перевернуть бремя доказательства.

Обновление: Эрик спросил о примере.

Как насчет этого (пока не знаю, имеет ли это смысл: -))

public class Lookup<out T> where T : Animal {
  public T Find(string name) {
    Animal a = _cache.FindAnimalByName(name);
    return a as T;
  }
}

var findReptiles = new Lookup<Reptile>();
Lookup<Animal> findAnimals = findReptiles;

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

Кстати, это подводит меня к необязательным параметрам типа в C # 5.0 : -)

Обновление 2: Я не утверждаю, что CLR и C # должны это разрешать. Просто пытаюсь понять, к чему это привело.

Ответы [ 3 ]

20 голосов
/ 30 марта 2010

Во-первых, как говорит Томас, он не поддерживается в CLR.

Во-вторых, как это будет работать?Предположим, что у вас

class C<out T>
{ ... how are you planning on using T in here? ... }

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

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

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

ОБНОВЛЕНИЕ: См.

Почему в C # 4.0 нет общей дисперсии для классов?

для более подробной информации по этому вопросу.

8 голосов
/ 30 марта 2010

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

(Поддержка этой функции для классов, безусловно, была бы полезна!)

1 голос
/ 24 августа 2011

Если бы они были разрешены, можно было бы определить полезные классы или структуры, не зависящие от типа (без внутренних типов), на 100%, которые были бы ковариантными относительно их типа T, если их конструктор принимал один или несколько поставщиков T или T. Могут быть определены полезные, безопасные на 100% типы классов или структур, которые будут противоречивы по отношению к T, если их конструкторы принимают одного или нескольких потребителей T. Я не уверен, что у интерфейса есть большое преимущество перед интерфейсом, кроме возможности использовать «новый», а не статический метод фабрики (скорее всего, из класса, имя которого похоже на имя интерфейса), но я могу Обязательно посмотрите варианты использования для того, чтобы неизменные структуры поддерживали ковариацию.

...