Литье объекта в IEnumerable [дубликат]

этот вопрос уже есть ответ здесь:

ниже приведена упрощенная версия проблемы, с которой я сталкиваюсь:

var list = new List<int> {1, 2, 3, 4, 5};
// list Count = 5 System.Collections.Generic.List<int>

var obj = list as object;
// obj  Count = 5   object {System.Collections.Generic.List<int>}

var enumerable = obj as IEnumerable<object>;
// enumerable   null    System.Collections.Generic.IEnumerable<object>

комментарии-это значения из окна просмотра в Visual Studio 2017

однако, если я введите:

obj as IEnumerable<object>

в окне часов я получаю:

obj as IEnumerable<object>  Count = 5   System.Collections.Generic.IEnumerable<object> {System.Collections.Generic.List<int>}

Так как же я могу бросить его в окно часов, и он работает, но если я делаю это в коде, он оценивается как null?

1 ответов


С в C# документация:

дисперсия в универсальных интерфейсах поддерживается только для ссылочных типов. Типы значений не поддерживают дисперсию. Например, IEnumerable<int> не может быть неявно преобразован в IEnumerable<object>, потому что целые числа представлены по типу значения.

что помогает знать здесь, так это то, что следующие две вещи очень различные операции под капотом:

var l = (object) new List<int>();
var i = (object) 42;

несмотря на синтаксис выглядит так же. Первая строка просто рассматривает список как другой тип (с некоторыми проверками, действительно ли может работать приведение), а вторая преобразование целое число в объект, содержащий его (бокс). Существует третий вариант, который вызывает оператор преобразования и по-прежнему выглядит одинаково. Поскольку первый вариант может ничего не менять в объекте и просто интерпретировать его по-другому, он намного дешевле второго. И я бы предположил, что в этом контексте здесь только вариант, который может работать для ковариации интерфейса.