Как выбрать IEnumerable<T> вместо List<T> из коллекции ICollection<T>?

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

Dictionary<Guid, List<T>> dictionary = source.ToDictionary(
  element => element.Id,
  element => element.Ts.ToList());

Тем не менее, я бы хотел, чтобы первая строка использовала IEnumerable, что создает ошибку несоответствия типов.

Dictionary<Guid, IEnumerable<T>> dictionary = source.ToDictionary( ... );

Использование ToArray вместо ToList мне не поможет (получаю ту же ошибку, плюс я научился не использовать массивы в C#, если это действительно не требуется) И, насколько я могу судить, тип Ts - ICollection.

Можно ли преобразовать весь шабанг так, как я хочу, не используя хардкор и не используя кастинг?

3 ответа

Решение

Если вы хотите избежать кастинга, вы можете использовать AsEnumerableметод расширения, который возвращает правильный тип, но также скрывает исходный экземпляр / реализацию за анонимным перечислимым.

Я бы лично просто использовал element => element.Ts as IEnumerable<T> однако, чтобы избежать вызова дополнительного метода только для удовлетворения ограниченного вывода обобщений.

Это потому что Dictionary<TKey, TValue> не является ковариантным. Так что вы не можете выбрать Dictionary<string, List<T>> и бросить его Dictionary<string, IEnumerable<T>> даже если List<T> инвентарь IEnumerable<T>, Зачем? Рассмотрим следующий код:

Dictionary<string, IEnumerable<int>> myDict = new Dictionary<string, List<int>>();
myDict.Add("key", new HashSet<int>());

С точки зрения компилятора это было бы совершенно нормально, потому что HashSet<T> инвентарь IEnumerable<T>, Но словарь ожидает, что значение будет List<T>!

Вы можете сделать бросок в ToDictionary метод:

Dictionary<Guid, IEnumerable<T>> dictionary = source.ToDictionary(
  element => element.Id,
  element => (IEnumerable<T>)element.Ts.ToList());

или предоставить параметры общего типа для ToDictionary вызов:

Dictionary<Guid, IEnumerable<T>> dictionary = source.ToDictionary<Guid, IEnumerable<T>>(
  element => element.Id,
  element => element.Ts.ToList());

Использование AsEnumerable(), который является удобным методом Linq, который просто возвращает источник приведения к IEnumerable<T>:

Dictionary<Guid, IEnumerable<T>> dictionary = source.ToDictionary(
  element => element.Id,
  element => element.Ts.AsEnumerable());

Вы также можете попробовать кастинг:

Dictionary<Guid, IEnumerable<T>> dictionary = source.ToDictionary(
  element => element.Id,
  element => (IEnumerable<T>)(element.Ts));
Другие вопросы по тегам