What's going on behind the scene of the 'f

2019-01-26 06:07发布

问题:

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.

回答1:

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



回答2:

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.



回答3:

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.



标签: c# foreach clr