Компилятор создает конечный автомат от вашего имени.
Из спецификации языка:
10,14 Итераторы
10.14.4 Объекты-перечислители
Когда член функции возвращает
тип интерфейса перечислителя
реализовано с использованием блока итератора,
вызов функции-члена не
немедленно выполнить код в
блок итератора. Вместо этого перечислитель
Объект создан и возвращен. это
объект инкапсулирует указанный код
в блоке итератора, и выполнение
кода в блоке итератора
происходит, когда объект перечислителя
Метод MoveNext вызывается.
объект перечислителя имеет следующее
Характеристики:
• Реализует
IEnumerator и IEnumerator, где
T - тип доходности итератора.
• Реализует System.IDisposable.
• Инициализируется с копией
значения аргумента (если есть) и экземпляр
значение передано члену функции.
• У него четыре потенциальных состояния,
до, работает, приостановлено, и после,
и изначально находится в предыдущем состоянии.
Объект перечислителя обычно является
экземпляр сгенерированный компилятором
класс перечислителя, который инкапсулирует
код в блоке итератора и
реализует интерфейсы перечислителя,
но другие способы реализации
возможны Если класс перечислителя
генерируется компилятором, что
класс будет вложенным, напрямую или
косвенно, в классе, содержащем
член функции, он будет иметь
частная доступность, и это будет
иметь имя, зарезервированное для использования компилятором
(§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;
}
}
}
}