taf*_*afa 4 compiler-construction iterator yield-keyword
我一直在使用迭代器,我喜欢它们.
但是虽然我已经仔细考虑过,但我无法弄清楚"如何识别迭代器的编译器".我也研究过它,但找不到任何资源来解释编译器设计上下文中的情况.
详细说来,大多数关于迭代器的文章暗示存在某种实现所需行为的"魔法".他们建议编译器维护一个状态机,以便跟踪执行的位置(可以看到最后一次'yield return').我对迭代器的这个属性特别感兴趣,可以进行惰性求值.
顺便说一句,我知道什么是状态机,已经采用了编译器设计课程,研究过龙书.但显然,我无法将我所研究的内容与csc的"魔法"联系起来.
任何知识或差异的想法都表示赞赏.
它比看起来更简单.编译器可以将迭代器函数分解为单个块; 块被yield语句划分.
状态机只需要跟踪我们当前所在的块,并在下次调用迭代器时直接跳转到此块.我们还需要跟踪所有局部变量(当然).
然后,我们需要考虑一些特殊情况,特别是包含yields的循环.幸运的是,IL(但不是C#本身)允许goto跳转到循环并恢复它们.
请注意,有一些非常复杂的边缘情况,例如C#不允许yield在finally块中,因为将函数保留为非常困难(不可能?)yield,然后恢复函数,执行清理,重新抛出任何异常并保留堆栈跟踪.
Eric Lippert发布了对该流程的深入描述.(阅读他所链接的文章!)