Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# i收集<;T>;不基于索引,但存在TakeWhile()_C#_.net_Collections - Fatal编程技术网

C# i收集<;T>;不基于索引,但存在TakeWhile()

C# i收集<;T>;不基于索引,但存在TakeWhile(),c#,.net,collections,C#,.net,Collections,我试图将T[]或List的用法作为函数参数和返回值替换为更合适的类型,如IEnumerable、ICollection和IList 据我理解,ICollection比IList更可取,因为它只需要基本/简单的收集功能(例如枚举器和计数功能),因为它提供的限制最少。从这里开始阅读,我认为一个主要的区别是,ICollection不要求基础集合基于索引,而IList需要这样做 在切换我的List引用时,我需要替换一个List.GetRange()调用,我非常惊讶地发现ICollection.TakeW

我试图将
T[]
List
的用法作为函数参数和返回值替换为更合适的类型,如
IEnumerable
ICollection
IList

据我理解,
ICollection
IList
更可取,因为它只需要基本/简单的收集功能(例如枚举器和计数功能),因为它提供的限制最少。从这里开始阅读,我认为一个主要的区别是,
ICollection
不要求基础集合基于索引,而
IList
需要这样做

在切换我的
List
引用时,我需要替换一个
List.GetRange()
调用,我非常惊讶地发现
ICollection.TakeWhile()
扩展方法有一个重载支持基于索引的选择


我不明白为什么这个方法存在于ICollection上,而没有基于这个接口的索引?我是否误解了,或者如果底层集合是哈希集或其他什么,那么这个方法实际上是如何工作的?

该方法与大多数LINQ一样,是在
IEnumerable
上的。任何只将索引器传递给使用者的功能(如
TakeWhile
)只需在递增计数器时循环即可。一些API可能能够使用索引器进行优化,然后由它们决定是否这样做,或者只是使用
IEnumerable
并简单地跳过(等)不需要的数据

例如:

int i = 0;
foreach(var item in source) {
    if(!predicate(i++, item)) break;
    yield return item;
}

与大多数LINQ一样,该方法位于
IEnumerable
上。任何只将索引器传递给使用者的功能(如
TakeWhile
)只需在递增计数器时循环即可。一些API可能能够使用索引器进行优化,然后由它们决定是否这样做,或者只是使用
IEnumerable
并简单地跳过(等)不需要的数据

例如:

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;
}

索引可以在集合不支持的情况下完成

int i = -1;

foreach(var item in collection)
{
   i++;
   // item is at index i;
}
类中的其他扩展方法在所有实现的类型上工作。它们都迭代集合(使用
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;
    }
}
private静态IEnumerable TakeWhile(IEnumerable源,Func谓词)
{
foreach(源中的TSource项)
{
if(!谓词(项))
{
打破
}
收益回报项目;
}
}
如您所见,它只是在集合上迭代,并计算谓词。这几乎适用于所有其他LINQ方法。当您使用任何其他集合(如
HashSet

和类中的其他扩展方法)处理所有实现的类型时,也会发生同样的情况。它们都迭代集合(使用
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;
    }
}
private静态IEnumerable TakeWhile(IEnumerable源,Func谓词)
{
foreach(源中的TSource项)
{
if(!谓词(项))
{
打破
}
收益回报项目;
}
}
如您所见,它只是在集合上迭代,并计算谓词。这几乎适用于所有其他LINQ方法。当您使用任何其他集合(如
HashSet
)时,也会发生同样的情况