需要帮助理解IEnumerable中的C#产量吗

需要帮助理解IEnumerable中的C#产量吗,c#,C#,我正在读C#2010加速版。我得不到什么yield 调用GetEnumerator时,代码 在包含产量的方法中 语句并不是在 那个时间点。相反 编译器生成一个枚举数 类,该类包含 屈服分组码 public IEnumerator GetEnumerator(){ foreach(项中的T项){ 收益回报项目; } } 我也读过 yield只是一个懒惰的数据生产者 在第一个项目之后生产另一个项目 已检索,而正在返回 列表将在一个列表中返回所有内容 去吧 这是否意味着每次调用GetEnumer

我正在读C#2010加速版。我得不到什么yield

调用GetEnumerator时,代码 在包含产量的方法中 语句并不是在 那个时间点。相反 编译器生成一个枚举数 类,该类包含 屈服分组码

public IEnumerator GetEnumerator(){
foreach(项中的T项){
收益回报项目;
} 
} 
我也读过

yield只是一个懒惰的数据生产者 在第一个项目之后生产另一个项目 已检索,而正在返回 列表将在一个列表中返回所有内容 去吧


这是否意味着每次调用
GetEnumerator
都将从集合中获取1项?所以第一次呼叫我得到第一个项目,第二个,我得到第二个,依此类推

是的,没错,下面的例子说明了如何使用它

public class List
{
    //using System.Collections;
    public static IEnumerable Power(int number, int exponent)
    {
        int counter = 0;
        int result = 1;
        while (counter++ < exponent)
        {
            result = result * number;
            yield return result;
        }
    }

    static void Main()
    {
        // Display powers of 2 up to the exponent 8:
        foreach (int i in Power(2, 8))
        {
            Console.Write("{0} ", i);
        }
    }
}
/*
Output:
2 4 8 16 32 64 128 256 
*/
公共类列表
{
//使用系统集合;
公共静态IEnumerable幂(整数,整数指数)
{
int计数器=0;
int结果=1;
while(计数器+++<指数)
{
结果=结果*编号;
收益结果;
}
}
静态void Main()
{
//显示指数8之前的2的幂:
foreach(int i掌权(2,8))
{
Console.Write(“{0}”,i);
}
}
}
/*
输出:
2 4 8 16 32 64 128 256 
*/

看起来你明白了

如您所述,
yield
用于类的
GetEnumerator
,以便您可以编写如下代码:

foreach (MyObject myObject in myObjectCollection)
{
    // Do something with myObject
}
通过从第一次调用返回第一项,从第二次调用返回第二项,依此类推,您可以循环集合中的所有元素


yield
是在
MyObjectCollection
中定义的,考虑它的最佳方式是当您第一次从
IEnumerator
请求项目时(例如在
foreach
中),它开始通过该方法运行,当它点击一个
yield return
时,它会暂停执行并返回该项供您在
foreach
中使用。然后,您请求下一个项目,它在其离开的位置恢复代码并重复该循环,直到遇到
屈服中断
或方法结束

public IEnumerator<string> enumerateSomeStrings()
{
    yield return "one";
    yield return "two";
    var array = new[] { "three", "four" }
    foreach (var item in array)
        yield return item;
    yield return "five";
}
public IEnumerator EnumerationSomeString()
{
收益率回报率“一”;
收益率回报率“二”;
var数组=新[]{“三”,“四”}
foreach(数组中的变量项)
收益回报项目;
收益率回报率“五”;
}

如果我理解你的问题是正确的,那么你的理解是错误的,我很震惊。yield语句(yield-return和yield-break)是一个非常聪明的编译器技巧。方法中的代码实际上被编译成一个实现IEnumerable的类。该方法将返回此类的实例。让我们在调用ins时调用实例“ins”。GetEnumerator()您会得到一个IEnumerator,当序列没有更多元素(例如遇到产量中断)时,每次调用MoveNext()都会生成集合中的下一个元素(产量返回负责此部分)返回false,进一步调用将导致异常。因此,生成(next)元素的不是对GetEnumerator的调用,而是对MoveNext的调用。请看一下接口;这可能有助于澄清正在发生的事情。编译器将您的代码转换为一个类,该类同时实现
IEnumerable
IEnumerator
。对GetEnumerator()的调用只返回类本身


该实现基本上是一个状态机,对于MoveNext()的每次调用,它都会执行代码,直到下一个
产生返回值
,然后将Current设置为返回值。
foreach
循环使用此枚举器遍历枚举项,在循环的每次迭代之前调用MoveNext()。编译器在这里确实做了一些非常酷的事情,使
产生返回
成为语言中最强大的结构之一。从程序员的角度来看,这只是一种根据请求懒洋洋地返回项目的简单方法。

理解yield关键字的简单方法是,当使用 收益返回关键字。通常,当我们遍历集合并希望返回结果时,我们使用集合对象 保持结果。让我们看一个例子

公共静态列表乘法(整数,整数倍)

在上面的例子中,我想返回2乘以10的结果。所以我创建了一个乘法方法 它返回2乘以10的结果,我将结果存储在列表中,并且当我的main方法调用 使用乘法方法,控件在循环中迭代十次,并将结果存储在列表中。这是没有 使用收益率。假设我想用收益率来做这个,它看起来像

公共静态IEnumerable乘法(整数,整数倍)

现在乘法方法有了细微的变化,返回类型是IEnumerable,并且没有其他列表来保存 因为要使用Yield,返回类型必须是IEnumerable或IEnumerator,并且因为Yield提供有状态迭代,所以返回结果 我们不需要额外的课程来保持成绩。所以在上面的例子中,当从Main调用乘法方法时 方法,它计算第一次迭代的结果,并将结果返回到main方法,然后返回到循环和 计算第二次迭代的结果,并将结果返回给main方法。这样,将结果返回给调用方 在每次迭代中一个接一个地使用方法。还有其他关键字break与Yield结合使用,导致迭代 停止。例如,在上面的例子中,如果我只想计算乘法的一半(10/2=5),那么 方法如下所示:

foreach (MyObject myObject in myObjectCollection)
{
    // Do something with myObject
}
公共街
    {
        List<int> resultList = new List<int>();
        int result = number;
        for(int i=1;i<=times;i++)
        {
            result=number*i;
            resultList.Add(result);
        }
        return resultList;
    }
    {
        foreach(int i in Multiplication(2,10))
        {
            Console.WriteLine(i);
        }
        Console.ReadKey();
    }
          {
        int result = number;
        for(int i=1;i<=times;i++)
        {
            result=number*i;
            yield return result;
        }
    }
    {
        foreach(int i in Multiplication(2,10))
        {
            Console.WriteLine(i);
        }
        Console.ReadKey();
    }
    {
        int result = number;
        for(int i=1;i<=times;i++)
        {
            result=number*i;
            yield return result;
            if (i == times / 2)
                yield break;
        }

    }