.NET IEnumerator <string> does not advance in MoveNext when in yield block

The code below (for working in LinqPad) is intended for parsing the string "foo / skip / bar" in object objects, skipping the bit "skip", giving Item objects for "foo" and "bar". At start up, 2 bars are produced.

In the TryGetChild method, when "skip" is found, the enumerator moves from "skip" forward to "bar". However, when execution returns to the calling method, the enumerator returns to skipping.

I think this is some kind of weirdness in the crop block, as if I split in Main () and pass the enumerator to Walk (), it works correctly. Can someone explain how the counter returns? Is a new one created?

edit: This is a very simplified version of the seemingly strange situation that I found in my code. I ask this question out of curiosity, and not looking for a workaround that I have already found.

/* output from program enumerator moved to foo enumerator moved to skip enumerator moved to bar enumerator moved to bar Item [] (3 items) foo bar bar */ static void Main() { Walk("foo/skip/bar").ToArray().Dump(); } private static IEnumerable<Item> Walk(string pathString) { var enumerator = pathString.Split('/').ToList().GetEnumerator(); var current = new Item() { S = "" }; while (enumerator.MoveNext()) { Console.WriteLine("enumerator moved to " + enumerator.Current); yield return current.TryGetChild(enumerator); } } class Item { public string S { get; set; } public Item TryGetChild(IEnumerator<string> enumerator) { if (enumerator.Current == "skip") { enumerator.MoveNext(); //iterator moves on to 123 Console.WriteLine("enumerator moved to " + enumerator.Current); } return new Item() { S = enumerator.Current }; } } 
+4
source share
2 answers

The reason you see this behavior is because List<T>.GetEnumerator() returns an instance of List<T>.Enumerator , which is a struct . Thus, you pass the value type to the TryGetChild() method, and any mutations of this type (including those made using MoveNext() ) will not be displayed in the caller.

+4
source

I think yield only works when using an IEnumerable or IEnumerable<T> loop.

0
source

Source: https://habr.com/ru/post/1369190/


All Articles