It will be called just once.
P.S. Calling it multiple times would make little sense. You would call it each time anew if you expected the result to be different each time. And how would you iterate over a continuously changing set?
You can determine this yourself by placing a breakpoint on the function "ReturnParts" If it is hits mutliple times for each iteration then yes it does.
It will only be called once.
The foreach
loop is equivalent to the following code:
IEnumerable<string> enumerator = (collection).GetEnumerator();
try {
while (enumerator.MoveNext()) {
string part = (string)enumerator.Current;
// Do Something or other.
}
} finally {
IDisposable disposable = enumerator as System.IDisposable;
if (disposable != null) disposable.Dispose();
}
In wondering the differences between for, foreach, while, and goto a few weeks ago so I wrote up this test code. All of the methods will compile into the same IL (other then a variable name on the foreach version.) In debug mode a few NOP statements will be in different positions.
static void @for<T>(IEnumerable<T> input)
{
T item;
using (var e = input.GetEnumerator())
for (; e.MoveNext(); )
{
item = e.Current;
Console.WriteLine(item);
}
}
static void @foreach<T>(IEnumerable<T> input)
{
foreach (var item in input)
Console.WriteLine(item);
}
static void @while<T>(IEnumerable<T> input)
{
T item;
using (var e = input.GetEnumerator())
while (e.MoveNext())
{
item = e.Current;
Console.WriteLine(item);
}
}
static void @goto<T>(IEnumerable<T> input)
{
T item;
using (var e = input.GetEnumerator())
{
goto check;
top:
item = e.Current;
Console.WriteLine(item);
check:
if (e.MoveNext())
goto top;
}
}
static void @gotoTry<T>(IEnumerable<T> input)
{
T item;
var e = input.GetEnumerator();
try
{
goto check;
top:
item = e.Current;
Console.WriteLine(item);
check:
if (e.MoveNext())
goto top;
}
finally
{
if (e != null)
e.Dispose();
}
}
Per @Eric's comment...
I have expanded for
, while
, 'goto' and foreach
with generic arrays. Now the for each
statement looks to use the indexer for the array. Object arrays and strings are expanded in similar ways. Objects will remove a boxing that occurs before the method call to Console.WriteLine and Strings will replace T item
and T[] copy...
with char item
and string copy...
respectively. Note that the critical section is no longer need because the disposable enumerator is no longer used.
static void @for<T>(T[] input)
{
T item;
T[] copy = input;
for (int i = 0; i < copy.Length; i++)
{
item = copy[i];
Console.WriteLine(item);
}
}
static void @foreach<T>(T[] input)
{
foreach (var item in input)
Console.WriteLine(item);
}
static void @while<T>(T[] input)
{
T item;
T[] copy = input;
int i = 0;
while (i < copy.Length)
{
item = copy[i];
Console.WriteLine(item);
i++;
}
}
static void @goto<T>(T[] input)
{
T item;
T[] copy = input;
int i = 0;
goto check;
top:
item = copy[i];
Console.WriteLine(item);
i++;
check:
if (i < copy.Length)
goto top;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With