我正在尝试将T[]
或List<T>
的用法替换为函数参数,并使用更合适的类型返回值,例如IEnumerable<T>
,ICollection<T>
和{{1} }。
IList<T>
优先于ICollection<T>
,您只需要基本/简单的集合功能(例如枚举器和计数功能),因为它提供的限制最少。从这里读到我认为的一个主要区别是IList<T>
不要求基础集合是ICollection<T>
所在的基于索引的那个?
在切换IList<T>
引用时,我需要替换List<T>
来电,我很惊讶地发现List<T>.GetRange()
扩展方法有一个过载支持基于索引的选择?! (msdn link)
我很困惑为什么这个方法存在于ICollection上,哪里没有基于此接口的索引?我是否误解了或者如果底层集合是例如Hashset或其他什么,这个方法如何实际工作?
答案 0 :(得分:2)
与大多数LINQ一样,该方法位于IEnumerable<T>
。只有将索引器传递给使用者的任何功能(例如TakeWhile
)只需要在递增计数器时循环。某些API可能能够使用索引器优化,然后由他们来决定是否这样做,或者只使用IEnumerable<T>
并简单地跳过(等)不需要的数据。 / p>
例如:
int i = 0;
foreach(var item in source) {
if(!predicate(i++, item)) break;
yield return item;
}
答案 1 :(得分:2)
索引可以在没有收集支持的情况下完成
int i = -1;
foreach(var item in collection)
{
i++;
// item is at index i;
}
答案 2 :(得分:0)
TakeWhile
类的 System.Linq.Enumerable
和其他扩展方法适用于实现IEnumerable<T>
的所有类型。它们都遍历集合(使用foreach
语句)并执行适当的操作。
以下是TakeWhile
方法的实现,并进行了一些简化:
private static IEnumerable<TSource> TakeWhile<TSource>(IEnumerable<TSource> source, Func<TSource, bool> predicate)
{
foreach (TSource item in source)
{
if (!predicate(item))
{
break;
}
yield return item;
}
}
如您所见,它只是遍历集合,并评估谓词。对于几乎所有其他LINQ方法都是如此。使用任何其他集合时也会发生同样的情况,例如HashSet<T>
。