我正在使用yield
和IEnumerable
,我现在很好奇以下代码段的工作原理或方式:
public class FakeList : IEnumerable<int>
{
private int one;
private int two;
public IEnumerator<int> GetEnumerator()
{
yield return one;
yield return two;
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
现在编译器如何转变:
public IEnumerator<int> GetEnumerator()
{
yield return one;
yield return two;
}
加入IEnumerator<int>
?
答案 0 :(得分:27)
使用yield return
时,编译器会为您生成枚举器类。因此,使用的实际代码比仅仅两个返回语句复杂得多。编译器添加所有必要的代码以返回枚举器,迭代来自yield return
的结果。
这是您FakeList.GetEnumerator()
生成的代码:
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.CompilerServices;
public class FakeList : IEnumerable<int>, IEnumerable
{
private int one;
private int two;
[IteratorStateMachine(typeof(<GetEnumerator>d__2))]
public IEnumerator<int> GetEnumerator()
{
yield return this.one;
yield return this.two;
}
IEnumerator IEnumerable.GetEnumerator() =>
this.GetEnumerator();
[CompilerGenerated]
private sealed class <GetEnumerator>d__2 : IEnumerator<int>, IDisposable, IEnumerator
{
private int <>1__state;
private int <>2__current;
public FakeList <>4__this;
[DebuggerHidden]
public <GetEnumerator>d__2(int <>1__state)
{
this.<>1__state = <>1__state;
}
private bool MoveNext()
{
switch (this.<>1__state)
{
case 0:
this.<>1__state = -1;
this.<>2__current = this.<>4__this.one;
this.<>1__state = 1;
return true;
case 1:
this.<>1__state = -1;
this.<>2__current = this.<>4__this.two;
this.<>1__state = 2;
return true;
case 2:
this.<>1__state = -1;
return false;
}
return false;
}
[DebuggerHidden]
void IEnumerator.Reset()
{
throw new NotSupportedException();
}
[DebuggerHidden]
void IDisposable.Dispose()
{
}
int IEnumerator<int>.Current =>
this.<>2__current;
object IEnumerator.Current =>
this.<>2__current;
}
}
你看到<GetEnumerator>d__2
班了吗?这是根据您的两个yield return
生成的。
答案 1 :(得分:12)
当编译器看到yield return
或yield break
时,它会接受该函数并将逻辑转换为实现状态机的类。调用该方法后,将返回此类的实例。
C# In Depth有一段关于代码的内容。
答案 2 :(得分:5)
这是一个发电机。 我不能说compilator是如何工作的,但是当你这样做时:
yield return x;
您不会像经典返回一样离开函数,而是返回一个值,然后继续执行该函数。
如果我记得很清楚,真正的可枚举和这个之间有一点区别,如果你不使用一种方法将你的生成器转换为真正的可枚举(取决于你想要完成的东西),你可以拥有一些麻烦。