当我有一个代码块
static void Main()
{
foreach (int i in YieldDemo.SupplyIntegers())
{
Console.WriteLine("{0} is consumed by foreach iteration", i);
}
}
class YieldDemo
{
public static IEnumerable<int> SupplyIntegers()
{
yield return 1;
yield return 2;
yield return 3;
}
}我能否解释收益回报背后的原则是
|1| |2| |3| are stored in contiguous memory block.Pointer of "IEnumerator" Moves to |1|澄清:
(1)通常我们将有一个有效的返回语句允许在function.How中执行C#处理,当多个收益率返回时,收益率返回,.有陈述吗?
(2)一旦遇到返回,就无法再次控制返回到SupplyIntegers(),如果允许的话,产量不会再次从1开始吗?我是说回报1?
发布于 2009-10-20 19:44:57
不,不是的,我会给你写个长版的.太下流了!
注意,如果您理解foreach实际上是:
using(var iterator = YieldDemo.SupplyIntegers().GetEnumerator()) {
int i;
while(iterator.MoveNext()) {
i = iterator.Current;
Console.WriteLine("{0} is consumed by foreach iteration", i);
}
}using System;
using System.Collections;
using System.Collections.Generic;
static class Program
{
static void Main()
{
foreach (int i in YieldDemo.SupplyIntegers())
{
Console.WriteLine("{0} is consumed by foreach iteration", i);
}
}
}
class YieldDemo
{
public static IEnumerable<int> SupplyIntegers()
{
return new YieldEnumerable();
}
class YieldEnumerable : IEnumerable<int>
{
public IEnumerator<int> GetEnumerator()
{
return new YieldIterator();
}
IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); }
}
class YieldIterator : IEnumerator<int>
{
private int state = 0;
private int value;
public int Current { get { return value; } }
object IEnumerator.Current { get { return Current; } }
void IEnumerator.Reset() { throw new NotSupportedException(); }
void IDisposable.Dispose() { }
public bool MoveNext()
{
switch (state)
{
case 0: value = 1; state = 1; return true;
case 1: value = 2; state = 2; return true;
case 2: value = 3; state = 3; return true;
default: return false;
}
}
}
}如您所见,它在迭代器中构建状态机,状态机由MoveNext推进。我在state字段中使用了这种模式,因为您可以看到这对于更复杂的迭代器是如何工作的。
重要的是:
finally块(包括using),那么它将进入Dispose()yield return的部分代码变为case (粗略地)yield break变成state = -1; return false; (或类似的)C#编译器这样做是非常复杂的,但它使编写迭代器变得轻而易举。
发布于 2009-10-20 19:47:34
它只是语法糖,.net为您生成IEnumerator类并实现MoveNext、当前方法和重置方法,而不是生成IEnumarable类GetEnumerator,后者返回IEnumerator,您可以通过.net反射器或ildasm看到神奇的类。
还请参见这里
发布于 2009-10-20 19:56:27
简单地说,迭代器块(如果可能的话是带有yield语句的方法)由编译器转换为编译器生成的类。该类实现IEnumerator,并将yield语句转换为该类的“状态”。
例如,这是:
yield return 1;
yield return 2;
yield return 3;可能会被转换成类似于:
switch (state)
{
case 0: goto LABEL_A;
case 1: goto LABEL_B;
case 2: goto LABEL_C;
}
LABEL_A:
return 1;
LABEL_B:
return 2;
LABEL_C:
return 3;Iterator块可以看作是抽象的状态机。此代码将由IEnumerator的方法调用。
https://stackoverflow.com/questions/1596863
复制相似问题