Possible Duplicate:
How do foreach loops work in C#?
I've been searching the internet and I'm having trouble finding any answers as to what's really going on behind the scenes with the foreach
loop in C#.
I know this question doesn't really pertain to actually coding but its bothering me. I'm pretty new to OO programming and especially interfaces. I understand they are contracts and I understand how IEnumerable
and IEnumerator
work - or so I think.
I've been reading this article on MSDN:
IEnumerable Interface
I understand how everything is set up. I'm a little unclear though in the Main
loop how the foreach
knows to itterate through all the values in _people
. How does it know this? How does it keep track of Current
by just calling return new PeopleEnum(_people);
?
EDIT: I don't see how this is an exact duplicate. Yes its similar grounds and the same question is being asked but we are looking for different answers or the answer I wanted was not discussed in the previous question.
A foreach loop like foreach(int i in obj) {...} kinda equates to
... is "kinda" not the answer I'm looking for.
I encourage you to read section 8.8.4 of the C# specification, which answers your question in detail. Quoting from it here for your convenience:
A foreach statement of the form
foreach (V v in x) embedded-statement
is then expanded to:
{
E e = ((C)(x)).GetEnumerator();
try
{
V v;
while (e.MoveNext())
{
v = (V)(T)e.Current;
embedded-statement
}
}
finally
{
code to Dispose e if necessary
}
}
The types E, C, V and T are the enumerator, collection, loop variable and collection element types deduced by the semantic analyzer; see the spec for details.
So there you go. A "foreach" is just a more convenient way of writing a "while" loop that calls MoveNext until MoveNext returns false.
A few subtle things:
This need not be the code that is generated; all that is required is that we generate code that produces the same result. For example, if you "foreach" over an array or a string, we just generate a "for" loop (or loops, in the case of multi-d arrays) that indexes the array or the chars of the string, rather than taking on the expense of allocating an enumerator.
If the enumerator is of value type then the disposal code might or might not choose to box the enumerator before disposing it. Don't rely on that one way or the other. (See http://blogs.msdn.com/b/ericlippert/archive/2011/03/14/to-box-or-not-to-box-that-is-the-question.aspx for a related issue.)
Similarly, if the casts automatically inserted above are determined to be identity conversions then the casts might be elided even if doing so would normally cause a value type to be copied.
Future versions of C# are likely to put the declaration of loop variable v
inside the while loop body; this will prevent the common "modified closure" bug that is reported about once a day on Stack Overflow. [Update: This change has indeed been implemented in C# 5.]
Consider it like this:
var enumerator = <YourEnumerableHere>.GetEnumerator();
while(enumerator.MoveNext())
<YourForEachMethodBodyHere>
Ergo, when it calls GetEnumerator
, you get back that result to the PeopleEnum
. Every time the MoveNext
method is called, the PeopleEnum
's position increases by one, iterating over the list.
When the position has reached the end, the MoveNext
call returns false, and the loop ends.
It knows to iterate through the IEnumerable
because that is what the language designers decided foreach
should do. foreach
is providing you a shorthand way of looping through an IEnumerable
yourself.
The IEnumerator
class is defining what it means to "get the next element". If you wanted to, you could make the IEnumerator
return every other element, but most people just want to go through each element sequentially.
I am not sure if I have answered your question. If not, let me know and I will respond.