2

I have the following problem: I have a list and add string items to this list. Then I create an Enumerator out of the list. When I loop through the list with the MoveNext() command it works when I access the enumerator directly. When I use the Enumerator properties to access the enumerator it doesn't work. The MoveNext() command doesn't increment the index.

Here is the code I used. Thanks a lot for your help.

public class DummyKlasse
{
    public List<string>.Enumerator enumerator;
    public List<string> list;

    public DummyKlasse()
    {
        Console.WriteLine("Test");
        list = new List<string>();
        enumerator = new List<string>.Enumerator();
    }

    public List<string>.Enumerator Enumerator
    {
        get { return enumerator; }
        set { enumerator = value;}
    }

    public List<string> List
    {
        get { return list; }
        set { list = new List<string>(value); }
    }        

    public void dummyfunction()
    {
        List.Add("test1");
        List.Add("test2");

        enumerator = List.GetEnumerator();
    }
}

public class Program
{
    static void Main(string[] args)
    {
        DummyKlasse dummyklasse = new DummyKlasse();
        dummyklasse.dummyfunction();

        //Does not work with properties
        /*
        while (dummyklasse.Enumerator.MoveNext())
        {
            Console.WriteLine(dummyklasse.Enumerator.Current);
        }
        */
        //Works WITHOUT properties
        while (dummyklasse.enumerator.MoveNext())
        {
            Console.WriteLine(dummyklasse.enumerator.Current);
        }

        Console.ReadLine();
    }
}
Ron.B.I
  • 2,726
  • 1
  • 20
  • 27
user2591237
  • 33
  • 1
  • 6

2 Answers2

4

List<T>.Enumerator is a struct, so in your while loop, each time you access the Enumerator property, you are calling the getter, which will return you a new copy of the enumerator each time. This enumerator will point to the item before th beginning of the list, and each call to MoveNext and Current will be done on a different copy of that enumerator.

As a result on a non-empty list, MoveNext will always return true, and Enumerator.Current is always null.

If you access the field directly, you are avoiding this copy and the same enumerator being accessed by the calls to MoveNext and Current.

If you change your code to:

using (var enumerator = dummyklasse.Enumerator)
{
    while (enumerator.MoveNext())
    {
        Console.WriteLine(enumerator.Current);
    }
}

it will work as expected. Note this is similar to what the foreach statement does.

Lee
  • 142,018
  • 20
  • 234
  • 287
  • How does this address the fact that directly accessing the field in the OP's example works but the property does not? – mao47 Jul 17 '13 at 12:18
  • 1
    @mao47 - If you access the field directly, you're not copying it. – Lee Jul 17 '13 at 12:19
  • For some reason I was still thinking of it as a variable even though I *knew* that it was a value. Structs can be tricky. – mao47 Jul 17 '13 at 12:26
  • Thanks a lot. I didn't know that it will make a copy of the struct. – user2591237 Jul 17 '13 at 14:35
0

Why are you trying to capture an enumerator in your DummyKlasse? Better just to capture the List itself (which you are doing), and let consumers worry about their own enumerators. This is best done with the use of a foreach loop.

public class DummyKlasse
{
    public List<string> List { get; set; }

    public DummyKlasse() 
    {
        List = new List<string>();
    }

    public void Setup()
    {
        List.Add("one");
        List.Add("two");
    }
}

...

var dummy = new DummyKlasse();
dummy.Setup();

// the client does his own enumerating, not dummy.
foreach (var str in dummy.List)   
{
    Console.WriteLine(str);
}
CSJ
  • 3,641
  • 2
  • 19
  • 29