Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Enumerator as an argument

Okay, let's start with this very simple button click method

    private void button1_Click(object sender, EventArgs e)
    {
        int counter = 1;
        List<int> items = new int[] { 1, 2, 3 }.ToList();
        List<int>.Enumerator enm = items.GetEnumerator();

        // 1
        if (!enm.MoveNext())
            throw new Exception("Unexpected end of list");
        if (enm.Current != counter)
            throw new Exception(String.Format("Expect {0} but actual {1}", counter, enm.Current));
        counter++;

        // 2
        if (!enm.MoveNext()) 
            throw new Exception("Unexpected end of list");
        if (enm.Current != counter) 
            throw new Exception(String.Format("Expect {0} but actual {1}", counter, enm.Current));
        counter++;

        //3
        if (!enm.MoveNext())
            throw new Exception("Unexpected end of list");
        if (enm.Current != counter)
            throw new Exception(String.Format("Expect {0} but actual {1}", counter, enm.Current));
        counter++;

        if (enm.MoveNext()) 
            throw new Exception("Unexpected continuation of list");
    }

This method do nothing because every assertion gracefully pass. Things are fine until I believe I should introduce a method to remove redundancy

    static void AssertNext(ref int counter, List<int>.Enumerator e)
    {
        if (!e.MoveNext()) 
            throw new Exception("Unexpected end of list");
        if (e.Current != counter) 
            throw new Exception(String.Format("Expect {0} but actual {1}", counter, e.Current));
        counter++;
    }

    private void button2_Click(object sender, EventArgs e)
    {
        var counter = 1;
        var items = new int[] { 1, 2, 3 }.ToList();
        var enm = items.GetEnumerator();
        AssertNext(ref counter, enm);
        AssertNext(ref counter, enm);
        AssertNext(ref counter, enm);
        if (enm.MoveNext()) throw new Exception("Unexpected continuation of list");
    }

Even though, this refactoring is straightforward (for me, at least). It does break the program ! On the second call to AssertNext, it seems like the enumerator was already reset to the starting point and cause the assertion to fail.

I cannot understand what happen. I really feel like a beginner with this puzzle.

What I miss here ?

like image 717
Sake Avatar asked Feb 22 '23 05:02

Sake


2 Answers

I'm imagining it has something to do with List.Enumerator being a struct. You're passing it to a method, manipulating it, and then returning. The manipulation will probably not have happened for your original instance.

like image 133
Jerome Haltom Avatar answered Mar 02 '23 03:03

Jerome Haltom


List<T>.Enumerator is a value type meaning that it's copied into the local scope of your method, altered, and then destroyed upon leaving the method. Try passing it by reference too.

like image 34
asdfjklqwer Avatar answered Mar 02 '23 02:03

asdfjklqwer