Почему С# (4.0) не допускает совпадения и контравариантность в типах универсального класса? - программирование
Подтвердить что ты не робот

Почему С# (4.0) не допускает совпадения и контравариантность в типах универсального класса?

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

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

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

Update: Эрик спросил о примере.

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

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;

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

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

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

4b9b3361

Ответ 1

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

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

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

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

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

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

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

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

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

Ответ 2

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

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

Ответ 3

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