标签:soft member evb 编译 count 复杂 await exp next
原文地址在这里。
虽然是很老的文章,但是这个博客内容里,有很多很有用的内容。
迭代器,Iterator很多语言中都有的概念,对应C#中比如IEnumerable
类。
C#中的Iterator是一个复杂的语法糖,在定义一个Iterator时,一般通过一个含有yield return
的函数来实现。
这背后的思想是,这个Iterator
以及和它有关的变量,都被编译器封装在了一个Helper类中,在这个Helper类中,还会维护一个State
状态变量,维护当前Iterator上次使用的状态。
比如如下代码中,CountFrom
返回一个从start
到limit
的int型iterator。
class MyClass {
int limit = 0;
public MyClass(int limit) {
this.limit = limit;
}
public IEnumerable<int> CountFrom(int start)
{
for (int i = start; i <= limit; i++) {
yield
return i;
}
}
}
编译器会将CountFrom
转换为一个Helper类,而其内部有一个状态机:
class MyClass_Enumerator: IEnumerable < int > {
int state$0 = 0; // internal member
int current$0; // internal member
MyClass this$0; // implicit parameter to CountFrom
int start; // explicit parameter to CountFrom
int i; // local variable of CountFrom
public int Current {
get {
return current$0;
}
}
public bool MoveNext()
{
switch (state$0) {
case 0:
goto resume$0;
case 1:
goto resume$1;
case 2:
return false;
}
resume$0: ;
for (i = start; i <= this$0.limit; i++) {
current$0 = i;
state$0 = 1;
return true;
resume$1: ;
}
state$0 = 2;
return false;
}
......
下面还有一些在这里无关紧要的代码…
}
public IEnumerable<int> CountFrom(int start)
{
MyClass_Enumerator e = new MyClass_Enumerator();
e.this$0 = this;
e.start = start;
return e;
}
其中:
start$0
,current$0
是内部变量维护start
和i
是实际遍历使用的变量state$0
和resume$0/1/..
维护了当前iterator的执行状态,有执行过程中,执行开始,执行结束
yield return
,那么相应的状态result$n
也会增加实际的逻辑,就写在MyClass_Enumerator
类的MoveNext
中,每次向前取值后,通过Current
返回当前值。
下次再次进入时,由于内部类保证了状态,可以从上一次开始继续取值。
这种内部类的方法,相比较递归方式,更节省栈空间,因为类是分配在堆上的。
这种通过yield return
+状态机的思想,也是后面c#异步编程async await
等的一种思想。
通过一个helper类,记录之前的状态,下次进入直接从之前的状态执行
标签:soft member evb 编译 count 复杂 await exp next
原文地址:https://www.cnblogs.com/mosakashaka/p/12804832.html