IEnumerable<T>
ковариантно в T
, поэтому это было бы разрешено:
IEnumerable<Giraffes> giraffes = ....
var animals = (IEnumerable<Animal>)giraffes;
Итак, почему же это не работает?
var array = new[] { 1, 2, 3 };
var objects = (IEnumerable<object>)array; //will not compile
int
extends object
, верно?
Ну, причина в том, что изменение типов в C# допускается только между ссылочными типами ; правило состоит в том, что дисперсия должна препятствовать идентичности, и в C # невозможно привести тип значения, сохраняющий идентичность; могут использоваться только ссылочные типы, и эти типы преобразования называются ссылочными преобразованиями :
var animal = (Animal)giraffe;
var o = (object)"Hello";
IFish fish = cod;
//etc.
Биты, составляющие объект не изменяются , только тип Ссылка меняется, отсюда и название преобразования. Обратите внимание, что в самом первом примере animals
и giraffes
- это один и тот же объект, object.ReferenceEquals(animals, giraffes)
вернет true
; мы изменили только тип ссылающейся на него переменной.
В вашем случае, чтобы получить IEnumerable<object>
из IEnumerable<someValueType>
, вам нужно будет перечислить и поместить в коробку каждый элемент , создавая новый перечислимый желаемого типа. Для этого вы можете использовать метод расширения Enumerable.Cast<T>()
:
IEnumerable<object> objects = array.Cast<object>();
Или сделать проекцию самостоятельно:
IEnumerable<object> objects = array.Select(i => (object)i);