Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What's going on behind the scene of the 'foreach' loop? [duplicate]

Tags:

c#

foreach

clr

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.

like image 734
Adam Beck Avatar asked Sep 08 '11 15:09

Adam Beck


2 Answers

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.]

like image 103
Eric Lippert Avatar answered Oct 05 '22 09:10

Eric Lippert


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.

like image 23
Tejs Avatar answered Oct 05 '22 09:10

Tejs