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