.NET IEnumerator<;字符串>;处于屈服块时,不在MoveNext上前进

.NET IEnumerator<;字符串>;处于屈服块时,不在MoveNext上前进,.net,yield-return,.net,Yield Return,下面的代码(用于在LinqPad中运行)旨在将“foo/skip/bar”字符串解析为项目对象,跳过“skip”位,生成“foo”和“bar”的项目对象。运行时,会产生2个“条形”项目 在TryGetChild方法中,当找到“skip”时,枚举数将从“skip”向前移动到“bar”。但是,当执行返回到调用方法时,枚举数返回“跳过” 我认为这有点奇怪,好像我在Main()中进行了拆分,并将枚举数传递到Walk()中,它工作正常。有人能解释一下统计员是怎么回去的吗?是否正在创建一个新的 编辑:这是我

下面的代码(用于在LinqPad中运行)旨在将“foo/skip/bar”字符串解析为项目对象,跳过“skip”位,生成“foo”和“bar”的项目对象。运行时,会产生2个“条形”项目

在TryGetChild方法中,当找到“skip”时,枚举数将从“skip”向前移动到“bar”。但是,当执行返回到调用方法时,枚举数返回“跳过”

我认为这有点奇怪,好像我在Main()中进行了拆分,并将枚举数传递到Walk()中,它工作正常。有人能解释一下统计员是怎么回去的吗?是否正在创建一个新的

编辑:这是我在代码中发现的看似奇怪的情况的一个非常简化的版本。我问这个问题是出于好奇,而不是寻找一个我已经找到的解决办法

/* 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 };
    }
}
/*程序的输出
枚举数已移动到foo
枚举数已移动到跳过
枚举数已移动到条
枚举数已移动到条
项目[](3项)
福
酒吧
酒吧
*/     
静态void Main()
{
步行(“foo/skip/bar”).ToArray().Dump();
}
私有静态IEnumerable Walk(字符串路径字符串)
{
var enumerator=pathString.Split('/').ToList().GetEnumerator();
var current=新项(){S=”“};
while(枚举数.MoveNext())
{
Console.WriteLine(“枚举器移动到”+枚举器.Current);
产生返回电流TRYGETCILD(枚举器);
}
}
类项目
{
公共字符串S{get;set;}
公共项TryGetChild(IEnumerator枚举器)
{
if(enumerator.Current==“跳过”)
{
枚举数.MoveNext();//迭代器转到123
Console.WriteLine(“枚举器移动到”+枚举器.Current);
}
返回新项(){S=enumerator.Current};
}
}

我认为
yield
仅在使用
IEnumerable
IEnumerable
循环时有效。

看到这种行为的原因是
List.GetEnumerator()
返回
List.Enumerator
的实例,这是一个结构。因此,您正在将值类型传递给
TryGetChild()
方法,并且该类型上的任何突变(包括由
MoveNext()
完成的突变)都不会反映在调用方中。

您的代码需要使用此方法的原因是什么?你的目标似乎可以用一种简单得多的方式实现。你能澄清一下你所说的“只起作用”是什么意思吗。。。当然,如果他不尝试用一个单独的方法来推进迭代器,它会工作得很好。
yield
绝对不是问题所在。看看我的答案到底是怎么回事。妈的,我也刚刚得出那个结论(虽然不是看IL,只是按照你在最后一句话中所建议的去做。这是一个很好的选择。”克里斯说,它是,而且不是。一般来说,这是很好的,但是依赖于一个枚举者的传递是自讨苦吃。是的,我确实考虑到了我的评论。“还有另一个我从不直接使用统计员的原因。乍一看似乎很安全…:)@Chris是的,我花了一分钟才意识到发生了什么。“嗯,变化应该反映出来,因为他传递了一个参考。等等……他是……啊哈!“@mcintyre321:不,var与此无关。如果将其作为显式类型定义,则会得到完全相同的行为。要避免此错误,需要将迭代器作为引用传递。基本上,它与引用和值类型的传递方式有关。这是一篇很好的文章,可能有助于解释此行为。