Перечислитель в качестве аргумента - PullRequest
4 голосов
/ 10 марта 2012

Хорошо, давайте начнем с этого очень простого метода нажатия кнопки

    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");
    }

Этот метод ничего не делает, потому что каждое утверждение изящно проходит. Все хорошо, пока я не считаю, что я должен ввести метод для устранения избыточности

    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");
    }

Хотя этот рефакторинг прост (по крайней мере, для меня). Это нарушает программу! При втором вызове AssertNext создается впечатление, что перечислитель уже сброшен до начальной точки, что приводит к сбою утверждения.

Я не могу понять, что случилось. Я действительно чувствую себя новичком в этой головоломке.

Что мне здесь не хватает?

Ответы [ 2 ]

5 голосов
/ 10 марта 2012

Я предполагаю, что это как-то связано с List.Enumerator, являющимся структурой.Вы передаете это методу, манипулируете им, а затем возвращаете.Манипулирование, вероятно, не произошло бы для вашего исходного экземпляра.

3 голосов
/ 10 марта 2012

List<T>.Enumerator - это тип значения, означающий, что он копируется в локальную область вашего метода, изменяется, а затем уничтожается при выходе из метода.Попробуйте передать его по ссылке.

...