ICollection 不是基于索引的,但 TakeWhile() 存在
本文关键字:存在 TakeWhile 索引 ICollection 于索引 | 更新日期: 2023-09-27 18:26:35
我正在尝试将T[]
或List<T>
的用法替换为函数参数,并用更合适的类型(例如IEnumerable<T>
,ICollection<T>
和IList<T>
(返回值。
ICollection<T>
根据我的理解,建议您只需要基本/简单的收集功能(例如枚举器和计数功能(IList<T>
,因为它提供了最少的限制。从阅读这里,我认为主要区别之一是ICollection<T>
不要求基础集合基于索引,而IList<T>
?
在切换我的List<T>
引用时,我需要替换一个List<T>.GetRange()
调用,我非常惊讶地发现ICollection<T>.TakeWhile()
扩展方法具有重载支持基于索引的选择?!(MSDN 链接(
我很困惑为什么这种方法存在于没有基于此接口的索引的 ICollection 上?我是否误解了,或者如果底层集合是例如哈希集或其他东西,这种方法如何实际工作?
与大多数 LINQ 一样,该方法位于 IEnumerable<T>
上。任何仅将索引器传递给使用者的功能(例如 TakeWhile
(只需要在递增计数器时进行循环。某些 API 可能能够使用索引器进行优化,然后由它们决定是否这样做,或者只使用IEnumerable<T>
并简单地跳过(等(不需要的数据。
例如:
int i = 0;
foreach(var item in source) {
if(!predicate(i++, item)) break;
yield return item;
}
可以在没有集合支持的情况下完成
int i = -1;
foreach(var item in collection)
{
i++;
// item is at index i;
}
System.Linq.Enumerable
类中的TakeWhile
和其他扩展方法适用于所有实现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>
.