假设我的代码如下:
(steam是文件流)
using(BinaryWriter bw = new BinaryWriter(stream))
{
foreach(byte[] b in BreakBytes(objectOfBytes))
{
writer.Write(b);
}
}
因此,要使BreakBytes工作,它必须执行以下操作:
public static IEnumerable<byte[]> BreakBytes(byte[] b)
{
..
while(..) {
yield return some_buffer;
}
..
}
收益究竟在做什么?它是否跟踪位置明智的位置?
我相信它会返回到调用的foreach循环,但是再次调用时会继续下一次迭代吗?
答案 0 :(得分:3)
简而言之,方法中的代码被重写为一个状态机,它会像你怀疑的那样:它跟踪它在循环中的位置,返回到调用者,并继续它停止的地方。
答案 1 :(得分:1)
yield
在C#中非常特殊,因为它不遵循正常的控制流程。
当迭代返回的IEnumerable
时,BreakBytes
函数将被调用并运行,直到它产生一个值。然后将控制权传递回foreach
循环。当循环步进到下一个项目时,BreakBytes
将恢复并运行,直到它到达另一个yield
。
这个有点奇怪的结构带来的好处是,如果只枚举IEnumerable
的一部分,则只需要生成该部分。
答案 2 :(得分:0)
Jon Skeet可以告诉你关于他们的一切:http://csharpindepth.com/Articles/Chapter6/IteratorBlockImplementation.aspx
是。它跟踪其内部状态。
答案 3 :(得分:0)
yield return语句是迭代器使用实现IEnumerable和IEnumerator接口的集合的GetEnumerator()和MoveNext()方法向调用者返回一个几乎总是foreach循环隐含的答案的点。 / p>
它确实保持了它的状态。像这样的迭代器块里面的代码可以被认为在yield return语句之后暂时停止,直到下次调用MoveNext()方法时它会向右移回它停止的位置,直到它达到另一个yield return。 / p>
对于更深入的解释,我强烈推荐这本书C# in Depth, Second Edition。