Yield 关键字的神奇之处
好吧,当我在构建自定义枚举器时,我注意到这种与yield有关的行为
假设你有这样的事情:
public class EnumeratorExample
{
public static IEnumerable<int> GetSource(int startPoint)
{
int[] values = new int[]{1,2,3,4,5,6,7};
Contract.Invariant(startPoint < values.Length);
bool keepSearching = true;
int index = startPoint;
while(keepSearching)
{
yield return values[index];
//The mind reels here
index ++
keepSearching = index < values.Length;
}
}
}
What made it possible under the compiler's hood toexecute the index ++以及在技术上从函数返回后 while 循环中的其余代码?
Ok, as I was poking around with building a custom enumerator, I had noticed this behavior that concerns the yield
Say you have something like this:
public class EnumeratorExample
{
public static IEnumerable<int> GetSource(int startPoint)
{
int[] values = new int[]{1,2,3,4,5,6,7};
Contract.Invariant(startPoint < values.Length);
bool keepSearching = true;
int index = startPoint;
while(keepSearching)
{
yield return values[index];
//The mind reels here
index ++
keepSearching = index < values.Length;
}
}
}
What makes it possible underneath the compiler's hood to execute the index ++ and the rest of the code in the while loop after you technically do a return from the function?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
编译器将代码重写为状态机。您编写的单个方法被分成不同的部分。每次调用
MoveNext
(隐式或显式)时,状态都会前进并执行正确的代码块。如果您想了解更多详细信息,建议阅读:
The compiler rewrites the code into a state machine. The single method you wrote is split up into different parts. Each time you call
MoveNext
(either implicity or explicitly) the state is advanced and the correct block of code is executed.Suggested reading if you want to know more details:
编译器代表您生成一个状态机。
从语言规范来看:
为了了解这一点,以下是 Reflector 如何反编译你的类:
The compiler generates a state-machine on your behalf.
From the language specification:
To get an idea of this, here's how Reflector decompiles your class:
产量是魔法。
嗯,不是真的。编译器生成一个完整的类来生成您正在执行的枚举。它基本上是糖,让你的生活更简单。
阅读此内容进行介绍。
编辑:这是错误的。链接已更改,请再次检查是否曾经有过。
Yield is magic.
Well, not really. The compiler generates a full class to generate the enumeration that you're doing. It's basically sugar to make your life simpler.
Read this for an intro.
EDIT: Wrong this. Link changed, check again if you have once.
这是 C# 编译器中最复杂的部分之一。最好阅读 Jon Skeet 的 C# in Depth 的免费示例章节(或者更好,获取这本书并阅读它:-)
进一步了解解释请参见 Marc Gravell 的回答:
That's one of the most complex parts of the C# compiler. Best read the free sample chapter of Jon Skeet's C# in Depth (or better, get the book and read it :-)
For further explanations see Marc Gravell's answer here:
这是一个优秀的博客系列(来自 Microsoft 资深人士 Raymond Chen),详细介绍了 Yield 的工作原理:
Here is an excellent blog series (from Microsoft veteran Raymond Chen) that details how yield works: