For example, if I have this code:
public static void Main(string[] args)
{
List<int> list = new List<int>() { 2, 3, 2, 9, 10, 2, 5 };
var out = list.Where(x => x == 2).Take(2).ToList();
}
Is the number of iterations 3 (as the second two is in index 2) or 7 (total number of elements)?
Thanks
Yes, stops.
You can see this clearly by rewriting the code as follows:
var result = list.Where(x =>
{
Console.WriteLine("Where: " + x);
return x == 2;
})
.Take(2).ToList();
list
will be iterated by the Where
function, returning only matching items.
Where
will be iterated by Take
, which stops after 2 results.
Take
is fully iterated by ToList
So the end result is that the iteration of list
is stopped by Take
at the second item of 2.
You can easily check it yourself. Let's test the hypothesis that 9
is reached (ie at least 4 items has been iterated):
var result = list
.Where(x => x == 2) // your query under test
.Take(2)
.Select(item => item != 9 // business as usual for the first 3 items
? item // throw exception on the 4th
: throw new Exception("Strange execution: 9 (4th item) has been scanned"))
.ToList(); // materialization executes the query
Run it and you'll see that 4th item ( 9
) has not been taken: no exception has been thrown.
I think the most convincing (and simple) answer is to look at the source code of TakeIterator
that runs when Take
is called:
static IEnumerable<TSource> TakeIterator<TSource>(IEnumerable<TSource> source, int count)
{
if (count > 0) {
foreach (TSource element in source) {
yield return element;
if (--count == 0) break; // Yep, it stops after "count" iterations
}
}
}
If you write some test code with your own IEnumerable and IEnumerator, it will be easy to see what happens.
class MyCollection : IEnumerable<int>
{
public List<int> Data {get; set;} = new List<int>() { 2, 3, 2, 9, 10, 2, 5 };
public IEnumerator<int> GetEnumerator()
{
return new MyEnumerator()
{
Data = this.Data,
};
}
}
And the enumerator:
class MyEnumerator : IEnumerator<int>
{
private int index = -1;
public List<int> Data {get; set;}
public void Reset()
{
this.index = -1;
}
public bool MoveNext()
{
++this.index;
return this.index < this.Data.Count;
}
public int Current
{
get
{
int returnValue = this.Data[this.index];
Debug.WriteLine("[{0}] {1}", this.index, returnValue);
return returnValue;
}
}
}
Test code:
void Main()
{
MyCollection collection = new MyCollection();
var out = collection.Where(x => x == 2).Take(2).ToList();
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.