551 字
3 分钟
[C#] 基于 yield 语句的迭代器逻辑懒执行
众所周知, C# 可以通过 yield 语句来快速向 IEnumerator 或者 IEnumerable 类型的方法返回值返回一个元素. 但它还有另外一个特性, 就是其内部逻辑的懒执行. 每两个 yield 语句之间的逻辑都是一个状态, 只有在调用迭代器的 MoveNext 方法后, 才会执行下一个状态的逻辑.
在文章中, 编译后的代码已经经过简化和删减, 以便于理解
迭代器方法的懒执行
举一个简单的例子:
IEnumerator SomeLogic(){ Console.WriteLine("hello world"); yield return null; Console.WriteLine("fuck you world");}在调用的时候, 逻辑并不会被立即执行, 只有对其返回的迭代器调用 MoveNext 的时候, 才会继续执行.
var enumerator = SomeLogic();
enumerator.MoveNext(); // 打印 hello worldenumerator.MoveNext(); // 打印 fuck you world迭代器方法的编译
在 C# 中, 使用了 yield 语句的, 返回 IEnumerator 或 IEnumerable 的方法, 会由编译器生成一个迭代器或可迭代类型, 在类型的内部包含该方法的逻辑.
例如上面提到的代码, 它会被编译成大概这样:
IEnumerator SomeLogic(){ return new SomeLogicEnumerator();}
private sealed class SomeLogicEnumerator : IEnumerator, IDisposable{ private int state; private object current;
object IEnumerator.Current { get { return current; } }
public SomeLogicEnumerator(int state) { this.state = state; }
void IDisposable.Dispose() { }
private bool MoveNext() { int num = state; if (num != 0) { if (num != 1) { return false; } state = -1; Console.WriteLine("AWA"); return false; } state = -1; Console.WriteLine("QWQ"); current = null; state = 1; return true; }
bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); }
void IEnumerator.Reset() { throw new NotSupportedException(); }}我们可以看到, 在这个迭代器类型中, 有一个 state 字段存储了当前的状态, 而在 MoveNext 被调用时, 会切换当前状态, 然后根据当前状态执行对应逻辑.
当然, 如果你的迭代器逻辑稍微长一些, 它也是可以处理的.
IEnumerator SomeLogic(){ Console.WriteLine("QWQ"); yield return 1; Console.WriteLine("AWA"); yield return 2; Console.WriteLine("QJFD"); yield return 3; Console.WriteLine("JWOEIJFOIWE");}它的 MoveNext 就变成了这样:
private bool MoveNext(){ switch (state) { case 0: Console.WriteLine("QWQ"); current = 1; state = 1; return true; case 1: Console.WriteLine("AWA"); current = 2; state = 2; return true; case 2: Console.WriteLine("QJFD"); current = 3; state = 3; return true; case 3: state = -1; Console.WriteLine("JWOEIJFOIWE"); return false; default: return false; }} [C#] 基于 yield 语句的迭代器逻辑懒执行
https://slimenull.com/posts/20231208192209/