简体   繁体   English

如何选择IEnumerable <T> 而不是列表 <T> 来自ICollection <T> ?

[英]How to pick IEnumerable<T> instead of List<T> from an ICollection<T>?

I have the following lines that work as supposed to. 我有以下几行按预期工作。

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

However, I'd like the first line to use IEnumerable , which creates an error of type mismatch. 但是,我希望第一行使用IEnumerable ,这会产生类型不匹配的错误。

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

Using ToArray instead of ToList won't help me (getting the same error, plus I've learned not to use arrays in C# unless really, really required) And as far I can tell, the type of Ts is ICollection . 使用ToArray而不是ToList不会对我有帮助(出现相同的错误,另外,我知道除非真的非常需要,否则我不会在C#中使用数组)据我所知, Ts的类型是ICollection

Is it possible to convert the whole shabang the way I wish without going hardcore and using casting? 是否可以按照我希望的方式转换整个shabang,而无需进行硬核转换和使用强制转换?

That's because Dictionary<TKey, TValue> is not covariant. 这是因为Dictionary<TKey, TValue>不是协变的。 So you can't pick Dictionary<string, List<T>> and cast it to Dictionary<string, IEnumerable<T>> even though List<T> implements IEnumerable<T> . 因此Dictionary<string, IEnumerable<T>>即使List<T>实现IEnumerable<T> Dictionary<string, List<T>>您也不能选择Dictionary<string, List<T>>并将其转换为Dictionary<string, IEnumerable<T>> Why? 为什么? Consider following code: 考虑以下代码:

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

From compiler perspective that would be totally ok, because HashSet<T> implements IEnumerable<T> . 从编译器的角度来看,这是完全可以的,因为HashSet<T>实现了IEnumerable<T> But the dictionary is expecting the value to be List<T> ! 但是字典期望值是List<T>

You can do a cast in ToDictionary method: 您可以使用ToDictionary方法进行ToDictionary

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

or provide generic type parameters to ToDictionary call: 或为ToDictionary调用提供通用类型参数:

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

Use AsEnumerable() , which is a handy Linq method that just returns the source cast to IEnumerable<T> : 使用AsEnumerable() ,这是一个方便的Linq方法,该方法仅将源强制转换返回到IEnumerable<T>

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

you could also try casting: 您也可以尝试投射:

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

If you want to avoid casting, you can use the AsEnumerable extension method, which would return the correct type, but also hide the original instance/implementation behind an anonymous enumerable. 如果要避免强制转换,可以使用AsEnumerable扩展方法,该方法将返回正确的类型,但也将原始实例/实现隐藏在匿名枚举后面。

I would personally just use element => element.Ts as IEnumerable<T> though, to avoid calling extra method only to satisfy the limited generics inference. 我个人只是将element => element.Ts as IEnumerable<T> ,以避免仅为了满足有限的泛型推断而调用额外的方法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM