Home > database >  Why Enumerator MoveNext() returns 0
Why Enumerator MoveNext() returns 0

Time:01-30

Why next code generates loop hangs?

var x = new
{
    Items = new List<int> { 1, 2, 3 }.GetEnumerator()
};

while (x.Items.MoveNext())
   Console.WriteLine(x.Items.Current);

If I get enumerator after x initialization, than everything works fine:

var x = new
{
    Items = new List<int> { 1, 2, 3 }
};

var enumerator = x.Items.GetEnumerator();

while (enumerator.MoveNext())
   Console.WriteLine(enumerator.Current);

Tried to decompile both code blocks, but don't understand the reason:

List<int> intList = new List<int>();
intList.Add(1);
intList.Add(2);
intList.Add(3);
var data1 = new \u003C\u003Ef__AnonymousType0<List<int>.Enumerator>(intList.GetEnumerator());
while (true)
{
   List<int>.Enumerator items = data1.Items;
   if (items.MoveNext())
   {
     items = data1.Items;
     Console.WriteLine(items.Current);
   }
   else
     break;
}
List<int> Items = new List<int>();
Items.Add(1);
Items.Add(2);
Items.Add(3);
var data2 = new \u003C\u003Ef__AnonymousType0<List<int>>(Items);
List<int>.Enumerator enumerator = data2.Items.GetEnumerator();
while (enumerator.MoveNext())
   Console.WriteLine(enumerator.Current);

CodePudding user response:

Because List's enumerator is a struct. In your first example, you're creating an enumerator object (somewhere, probably heap, doesn't matter) and every time you access it with .Items the enumerator gets copied onto the stack in your executing function. MoveNext mutates it and then the copied enumerator gets discarded. If it were a class, only the reference would be copied/discarded and the actual data modified but since it's a struct, you didn't modify the enumerator in var x { ... } at all. Enumerator.Current returns 0 because default(int) is zero but an exception would be possible, too.

In your second example you're creating a slot for the enumerator on the stack with var enumerator = x.Items.GetEnumerator(); and that slot gets accessed repeadedly without copies.

  • Related