I know that an IEnumerable<T>
does not iterate until it is called.
Suppose that I have this code:
foreach(int iteratorInt in myIEnumerable.OrderBy(x => x))
{
if(iteratorInt == myIEnumerable.First())
{
// do something
}
}
In the if
I am checking the first element, so does the myIEnumerable
have to be ordered at each iteration to see which one is the first element or is it ordered just once?
When using the LINQ extensions, the query will only be executed when requested, otherwise known as deferred execution. When the same query is requested multiple times, the underlying query is re-evaluated each time, unless the initial query has been materialized with something like .ToArrary()
or .ToList()
.
The question isn't entirely clear, so I'll provide a few examples demonstrating various behavior.
Ex 1:
Code:
private static void Ex1()
{
Console.WriteLine("A");
IEnumerable<int> myIEnumerable = GetEnumerable();
Console.WriteLine("B");
foreach (int i in myIEnumerable.OrderBy(x => x))
{
Console.WriteLine("*** foreach : " + i);
if (i == myIEnumerable.First())
{
Console.WriteLine("=== Matched .First() : " + i);
}
}
Console.WriteLine("C");
}
Ex 2:
Code:
private static void Ex2()
{
Console.WriteLine("A");
IEnumerable<int> myIEnumerable = GetEnumerable();
Console.WriteLine("B");
var ordered = myIEnumerable.OrderBy(x => x);
foreach (int i in ordered)
{
Console.WriteLine("*** foreach : " + i);
if (i == ordered.First())
{
Console.WriteLine("=== Matched .First() : " + i);
}
}
Console.WriteLine("C");
}
Ex 3:
Code:
private static void Ex3()
{
Console.WriteLine("A");
IEnumerable<int> myIEnumerable = GetEnumerable();
Console.WriteLine("B");
var ordered = myIEnumerable.OrderBy(x => x).ToArray();
foreach (int i in ordered)
{
Console.WriteLine("*** foreach : " + i);
if (i == ordered.First())
{
Console.WriteLine("=== Matched .First() : " + i);
}
}
Console.WriteLine("C");
}
All queries use the same method to get the enumerable:
private static IEnumerable<int> GetEnumerable()
{
Console.WriteLine("~~~ GetEnumerable Start");
foreach (int i in new[]{3, 2, 1})
{
Console.WriteLine(">>> yield return : " + i);
yield return i;
}
Console.WriteLine("~~~ GetEnumerable End");
}
The results will end up as:
====================
Ex A
====================
A
B
~~~ GetEnumerable Start
>>> yield return : 3
>>> yield return : 2
>>> yield return : 1
~~~ GetEnumerable End
*** foreach : 1
~~~ GetEnumerable Start
>>> yield return : 3
*** foreach : 2
~~~ GetEnumerable Start
>>> yield return : 3
*** foreach : 3
~~~ GetEnumerable Start
>>> yield return : 3
=== Matched .First() : 3
C
====================
Ex B
====================
A
B
~~~ GetEnumerable Start
>>> yield return : 3
>>> yield return : 2
>>> yield return : 1
~~~ GetEnumerable End
*** foreach : 1
~~~ GetEnumerable Start
>>> yield return : 3
>>> yield return : 2
>>> yield return : 1
~~~ GetEnumerable End
=== Matched .First() : 1
*** foreach : 2
~~~ GetEnumerable Start
>>> yield return : 3
>>> yield return : 2
>>> yield return : 1
~~~ GetEnumerable End
*** foreach : 3
~~~ GetEnumerable Start
>>> yield return : 3
>>> yield return : 2
>>> yield return : 1
~~~ GetEnumerable End
C
====================
Ex C
====================
A
B
~~~ GetEnumerable Start
>>> yield return : 3
>>> yield return : 2
>>> yield return : 1
~~~ GetEnumerable End
*** foreach : 1
=== Matched .First() : 1
*** foreach : 2
*** foreach : 3
C