Почему IEnumerator ‹T› не сохраняет состояние после передачи в функцию

Я вручную увеличиваю счетчик и передаю его функциям для обработки подмножеств данных. По возвращении из этих функций я обнаружил, что перечислитель не изменил состояние в родительской функции.

Вот упрощенная версия того, о чем я говорю.

class Program {
    static void Main(string[] args) {
        var input = new List<string>() {
            "1",
            "2",
            "escape",
            "3",
            "4",
            "return",
            "5"
        };

        foreach(var line in ParseFile(input)) {
            Console.WriteLine(line);
        }
        Console.ReadLine();
        Environment.Exit(Environment.ExitCode);
    }

    private static IEnumerable<string> ParseFile(List<string> input) {
        var enumerator = input.GetEnumerator();
        while (enumerator.MoveNext()) {
            if (enumerator.Current.Equals("escape")) {
                foreach (var line in DoStuff(enumerator)) {
                    yield return line;
                }
            } else {
                yield return enumerator.Current;
            }
        }
    }

    private static IEnumerable<string> DoStuff(IEnumerator<string> enumerator) {
        do {
            yield return enumerator.Current;
        } while (enumerator.MoveNext() && (!enumerator.Current.Equals("return")));
    }
}

Я вижу, что после выхода из DoStuff enumerator.Current по-прежнему ускользает и не увеличивается для возврата. Вот результаты с консоли:

1

2

побег

3

4

3

4

возвращение

5

Мой вопрос в том, что вызывает это? Передается ли во вторую функцию глубокая копия перечислителя? Если да, то почему это происходит? GetHashCode () одинаков для обоих объектов.


person Andrew Miller    schedule 25.05.2017    source источник
comment
List<T>.Enumerator - это структура, поэтому изменения функции происходят в копии.   -  person Lee    schedule 25.05.2017
comment
Передайте его по ссылке, если хотите сохранить состояние (DoStuff(ref IEnumerator<string> enumerator))   -  person Evk    schedule 25.05.2017
comment
stackoverflow .com / questions / 3168311 /   -  person Hans Passant    schedule 25.05.2017
comment
@Lee Это именно та информация, которую мне не хватало. Спасибо!   -  person Andrew Miller    schedule 25.05.2017
comment
Кроме того, var enumerator = input.GetEnumerator(); возвращает IEumerable<T> (T в данном случае string), который также наследует IDisposable и, следовательно, должен быть правильно Dispose(), заключив его время жизни в оператор using.   -  person Jesse C. Slicer    schedule 25.05.2017
comment
Проголосовали за, потому что, хотя это дубликат, моя конкретная поисковая фраза привела сюда, а не к одному из оригиналов.   -  person josh2112    schedule 20.12.2017