C# 收益率关键字的奇迹
好的,当我在构建一个自定义枚举器时,我注意到了这个与产量有关的行为 假设你有这样的东西:C# 收益率关键字的奇迹,c#,enumeration,yield,yield-return,C#,Enumeration,Yield,Yield Return,好的,当我在构建一个自定义枚举器时,我注意到了这个与产量有关的行为 假设你有这样的东西: public class EnumeratorExample { public static IEnumerable<int> GetSource(int startPoint) { int[] values = new int[]{1,2,3,4,5,6,7}; Contract.In
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;
}
}
}
公共类枚举器示例
{
公共静态IEnumerable GetSource(int startPoint)
{
int[]值=新的int[]{1,2,3,4,5,6,7};
收缩不变(起始点<值.长度);
bool keepsearch=true;
int索引=起始点;
同时(继续搜索)
{
收益率返回值[指数];
//我的脑子在这里转
索引++
keepSearching=索引<值.长度;
}
}
}
从技术上讲,从函数返回后,是什么使编译器能够在后台执行index++和while循环中的其余代码?编译器将代码重写到状态机中。您编写的单个方法被分成不同的部分。每次调用
MoveNext
(隐式或显式)时,状态都处于高级状态,并执行正确的代码块
如果您想了解更多详细信息,建议阅读:
- C#中迭代器的实现及其后果-Raymond Chen
- -乔恩·斯凯特
- 产量是神奇的
嗯,不是真的。编译器生成一个完整的类来生成您正在执行的枚举。它基本上是糖,让你的生活更简单
阅读介绍
编辑:这个错了。链接已更改,请再次检查是否有更改。编译器将代表您生成一个状态机 根据语言规范: 10.14迭代器 10.14.4枚举器对象 当函数成员返回 枚举器接口类型为 使用迭代器块实现, 调用函数成员不会 立即在 迭代器块。而是一个枚举器 对象被创建并返回。这 对象封装指定的代码 在迭代器块中,执行 迭代器块中的代码 在枚举器对象的 调用MoveNext方法。一 枚举器对象具有以下特性 特点: •它实现 IEnumerator和IEnumerator,其中 T是迭代器的屈服类型 •它实现System.IDisposable •它是用一份 参数值(如果有)和实例 传递给函数成员的值 •它有四种潜在状态, 之前、运行、暂停和之后, 并且最初处于before状态 枚举器对象通常是 生成的编译器的实例 封装 迭代器块中的代码和 实现枚举器接口, 但还有其他的实施方法 这是可能的。如果枚举器类 是由编译器生成的 类将直接或间接嵌套 间接地,在包含 函数成员,它将具有 私人可访问性,它将 保留一个名称供编译器使用 (§2.4.2) 为了了解这一点,以下是Reflector如何反编译您的类:
public class EnumeratorExample
{
// Methods
public static IEnumerable<int> GetSource(int startPoint)
{
return new <GetSource>d__0(-2) { <>3__startPoint = startPoint };
}
// Nested Types
[CompilerGenerated]
private sealed class <GetSource>d__0 : IEnumerable<int>, IEnumerable, IEnumerator<int>, IEnumerator, IDisposable
{
// Fields
private int <>1__state;
private int <>2__current;
public int <>3__startPoint;
private int <>l__initialThreadId;
public int <index>5__3;
public bool <keepSearching>5__2;
public int[] <values>5__1;
public int startPoint;
// Methods
[DebuggerHidden]
public <GetSource>d__0(int <>1__state)
{
this.<>1__state = <>1__state;
this.<>l__initialThreadId = Thread.CurrentThread.ManagedThreadId;
}
private bool MoveNext()
{
switch (this.<>1__state)
{
case 0:
this.<>1__state = -1;
this.<values>5__1 = new int[] { 1, 2, 3, 4, 5, 6, 7 };
this.<keepSearching>5__2 = true;
this.<index>5__3 = this.startPoint;
while (this.<keepSearching>5__2)
{
this.<>2__current = this.<values>5__1[this.<index>5__3];
this.<>1__state = 1;
return true;
Label_0073:
this.<>1__state = -1;
this.<index>5__3++;
this.<keepSearching>5__2 = this.<index>5__3 < this.<values>5__1.Length;
}
break;
case 1:
goto Label_0073;
}
return false;
}
[DebuggerHidden]
IEnumerator<int> IEnumerable<int>.GetEnumerator()
{
EnumeratorExample.<GetSource>d__0 d__;
if ((Thread.CurrentThread.ManagedThreadId == this.<>l__initialThreadId) && (this.<>1__state == -2))
{
this.<>1__state = 0;
d__ = this;
}
else
{
d__ = new EnumeratorExample.<GetSource>d__0(0);
}
d__.startPoint = this.<>3__startPoint;
return d__;
}
[DebuggerHidden]
IEnumerator IEnumerable.GetEnumerator()
{
return this.System.Collections.Generic.IEnumerable<System.Int32>.GetEnumerator();
}
[DebuggerHidden]
void IEnumerator.Reset()
{
throw new NotSupportedException();
}
void IDisposable.Dispose()
{
}
// Properties
int IEnumerator<int>.Current
{
[DebuggerHidden]
get
{
return this.<>2__current;
}
}
object IEnumerator.Current
{
[DebuggerHidden]
get
{
return this.<>2__current;
}
}
}
}
公共类枚举器示例
{
//方法
公共静态IEnumerable GetSource(int startPoint)
{
返回新的d_uu0(-2){3_uustartpoint=startPoint};
}
//嵌套类型
[编译生成]
私有密封类d_u0:IEnumerable,IEnumerable,IEnumerator,IEnumerator,IDisposable
{
//田地
私立国际1____州;
专用int 2_uuu电流;
公共int 3___起点;
private int l__initialThreadId;
公共int 5___3;
公共图书馆5_uu2;
公共int[]5___1;
公共国际起点;
//方法
[调试程序隐藏]
公共数据0(内部1状态)
{
这个1.1__状态=1__状态;
this.l__initialThreadId=Thread.CurrentThread.ManagedThreadId;
}
私有布尔移动下一个()
{
开关(此.1___状态)
{
案例0:
该状态为-1;
this.5_uu1=新的int[]{1,2,3,4,5,6,7};
这1.5__2=真;
this.5_uu3=this.startPoint;
而(这是第2.5条)
{
这个.2___电流=这个.5__1[这个.5__3];
该状态=1;
返回true;
标签_0073:
该状态为-1;
这个.5_uu3++;
此.5_uuu2=此.5_uu3<此.5_uu1.长度;
}
打破
案例1:
goto标签_0073;
}
返回false;
}
[调试程序隐藏]
IEnumerator IEnumerable.GetEnumerator()
{
枚举数示例.d_uu0 d_uuu;
if((Thread.CurrentThread.ManagedThreadId==this.l_uinitialThreadId)&&(this.1_u状态==-2))
{
该状态=0;
d_u;=这;
}
其他的
{
d_uu=新枚举数示例.d_u0(0);
}
d_uuu.startPoint=此.3_uuu起始点;
返回d__;
}
[调试程序隐藏]
IEnumerator IEnumerable.GetEnumerator()
{
返回此.System.Collections.Generic.IEnumerable.GetEnumerator();
}
[调试程序隐藏]
void IEnumerator.Reset()
{
抛出新的NotSupportedException();
}
void IDisposable.Dispose()无效
{
}
//性质
国际酒店