Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Strange behavior of Enumerator.MoveNext()

Could someone explain why this code is running in infinity loop? Why MoveNext() return true always?

var x = new { TempList = new List<int> { 1, 3, 6, 9 }.GetEnumerator() }; while (x.TempList.MoveNext()) {   Console.WriteLine("Hello World"); } 
like image 741
ivamax9 Avatar asked Jul 23 '15 15:07

ivamax9


People also ask

Why does MoveNext return false when changing enumerator?

When the enumerator is at this position, subsequent calls to MoveNext also return false until Reset is called. If changes are made to the collection, such as adding, modifying, or deleting elements, the behavior of MoveNext is undefined.

How do you move a char enumerator to the next character?

CharEnumerator.MoveNext () Method is used to increments the internal index of the current CharEnumerator object to the next character of the enumerated string. Return Value: This method returns the boolean value true value if the index is successfully incremented and within the enumerated string otherwise, false.

What is charenumerator MoveNext () method in Java?

Last Updated : 30 Apr, 2019 CharEnumerator.MoveNext () Method is used to increments the internal index of the current CharEnumerator object to the next character of the enumerated string.

How does the IEnumerator interface work?

This code example is part of a larger example for the IEnumerator interface. After an enumerator is created or after the Reset method is called, an enumerator is positioned before the first element of the collection, and the first call to the MoveNext method moves the enumerator over the first element of the collection.


1 Answers

List<T>.GetEnumerator() returns a mutable value type (List<T>.Enumerator). You're storing that value in the anonymous type.

Now, let's have a look at what this does:

while (x.TempList.MoveNext()) {     // Ignore this } 

That's equivalent to:

while (true) {     var tmp = x.TempList;     var result = tmp.MoveNext();     if (!result)     {         break;     }      // Original loop body } 

Now note what we're calling MoveNext() on - the copy of the value which is in the anonymous type. You can't actually change the value in the anonymous type - all you've got is a property you can call, which will give you a copy of the value.

If you change the code to:

var x = new { TempList = (IEnumerable<int>) new List<int> { 1, 3, 6, 9 }.GetEnumerator() }; 

... then you'll end up getting a reference in the anonymous type. A reference to a box containing the mutable value. When you call MoveNext() on that reference, the value inside the box will be mutated, so it'll do what you want.

For analysis on a very similar situation (again using List<T>.GetEnumerator()) see my 2010 blog post "Iterate, damn you!".

like image 148
Jon Skeet Avatar answered Sep 28 '22 16:09

Jon Skeet