嵌套IEnumerator未按预期运行:多次调用Run()仅输出‘One’
问题原因及解决方法
你遇到的问题核心是:在迭代器中yield return另一个IEnumerator时,C#不会自动递归执行这个子枚举器的内容。
原代码的执行流程是:
- 第一次调用
Run(),执行routine.MoveNext(),进入CountOne(),输出One,然后yield return CountTwo()——此时CountOne的迭代器暂停,MoveNext()返回true,但返回的是CountTwo的枚举器对象,你的代码没有对这个子枚举器做任何迭代操作。 - 第二次调用
Run(),继续执行CountOne迭代器中yield return之后的代码,此时没有更多可执行的内容,MoveNext()直接返回false,自然不会输出Two和Three。
解决方法
要让嵌套的迭代器依次执行,需要手动迭代子枚举器,最直接的方式是在父迭代器中用foreach遍历子枚举器的每一项,再yield return出去:
修改后的完整代码:
public class Test { private IEnumerator<Object> routine; public void Setup() { routine = CountOne(); } public void Run() { routine.MoveNext(); } private IEnumerator<Object> CountOne() { Console.WriteLine("One"); // 手动迭代CountTwo的所有项 foreach (var item in CountTwo()) { yield return item; } } private IEnumerator<Object> CountTwo() { Console.WriteLine("Two"); // 手动迭代CountThree的所有项 foreach (var item in CountThree()) { yield return item; } } private IEnumerator<Object> CountThree() { Console.WriteLine("Three"); yield return null; } }
现在多次调用Run()就会依次输出One、Two、Three:
- 第一次
Run():执行CountOne输出One,开始迭代CountTwo,执行CountTwo输出Two,开始迭代CountThree,执行CountThree输出Three,yield return null,MoveNext()返回true。 - 第二次
Run():继续CountThree的迭代,没有更多代码,回到CountTwo的foreach,没有更多项,回到CountOne的foreach,没有更多项,此时MoveNext()返回false。
内容的提问来源于stack exchange,提问作者Nefisto
相关产品推荐
相关产品推荐

