如何从ICollection <t>中选择IEnumerable <t>而不是List <t>?

时间:2015-07-14 22:11:16

标签: c# linq collections todictionary

我有以下几行可以正常工作。

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

是否有可能按照我希望的方式转换整个shabang而不用硬核并使用铸造?

3 个答案:

答案 0 :(得分:3)

那是因为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());

答案 1 :(得分:2)

使用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));

答案 2 :(得分:2)

如果你想避免强制转换,你可以使用AsEnumerable扩展方法,它会返回正确的类型,但也会隐藏匿名可枚举的原始实例/实现。

我个人只会使用element => element.Ts as IEnumerable<T>来避免调用额外的方法来满足有限的泛型推断。