Ответ 1
Отклонение (ковариация или контравариантность) не работает для типов значений, только ссылочные типы:
Отклонение применяется только к ссылочным типам; , если вы укажете тип значения для параметра типа варианта, , тип type является инвариантным для полученного построенного типа. (MSDN)
Значения, содержащиеся внутри переменных ссылочного типа, являются ссылками (например, адресами), а адреса данных имеют одинаковый размер и интерпретируются одинаково, без каких-либо изменений в их битовых шаблонах.
Напротив, значения, содержащиеся внутри переменных типа значения, не имеют одинакового размера или той же семантики. Использование их в качестве ссылочных типов требует бокса и бокса требует, чтобы компилятор выдавал инструкции по конкретному типу. Это не практично или эффективно (иногда, возможно, даже невозможно) для компилятора, чтобы испускать инструкции по боксу для любого возможного типа значения, поэтому дисперсия вообще не разрешена.
В принципе, дисперсия практична благодаря добавочному слою косвенности (ссылки) от переменной к фактическим данным. Поскольку типы значений не имеют этого слоя косвенности, им не хватает возможностей дисперсии.
Объедините вышеуказанное с тем, как работают операции LINQ:
ОперацияA Cast
активизирует/блокирует все элементы (путем доступа к ним через не общий IEnumerable
, как вы указали), а затем проверяет, что все элементы в последовательности могут быть успешно выбраны/распакованы в предоставленный тип а затем делает именно это. Операция ToList
перечисляет последовательность и возвращает список из этого перечисления.
У каждого есть своя работа. Если (скажем) ToList
выполнял работу обоих, у него были бы служебные издержки для обоих, что нежелательно для большинства других случаев.