I am Penny " }; yield return new Person { SaySome = " Hello

时间:2022-01-08 07:40:23

什么时候可以使用yield的关键字来界说迭代器?

迭代器的返回类型必需是IEnumerable、IEnumerable<T>、IEnumerator 或 IEnumerator<T>

迭代器的入参不能包孕ref或out类型的参数

首先,我们界说一个简单的遍历。

static void Main(string[] args) { List<Person> persons = new List<Person>(); persons.Add(new Person { SaySome = "Hello World,I am Sheldon" }); persons.Add(new Person { SaySome = "Hello World,I am Penny" }); persons.Add(new Person { SaySome = "Hello World,I am Amy" }); foreach (var item in persons) { Console.WriteLine(item.SaySome); } }

它的输出功效:

I am Penny " }; yield return new Person { SaySome = " Hello

接下来,我们使用yield,来实现同样的效果。

static void Main(string[] args) { foreach (var item in GetEnumerator()) { Console.WriteLine(item.SaySome); } } public static IEnumerable<Person> GetEnumerator() { yield return new Person { SaySome = "Hello World,I am Sheldon" }; yield return new Person { SaySome = "Hello World,I am Penny" }; yield return new Person { SaySome = "Hello World,I am Amy" }; }

虽然,我们得到了同样的功效,但是yield到底是如何做到的?

(又是翻书,又是看msdn,终于得到了答案)

使用yield语句时,它会自动生成一个枚举器,而不是仅仅生成一个包罗项的列表。

——————————————————    以上内容关于yield描述了概略    ———————————————————————

——————————————————以下内容主要说明foreach如何迭代———————————————————————

这个枚举器通过foreach挪用,foreach中依次访谒每一项时,就会访谒这个枚举器,,从而到达迭代大量数据,而无须一次把所有的数据写到内存中。

关于枚举器,我检察了system.collection.generic空间下的源码。

为了知道foreach中是如何通过枚举器来事情的。

我们来按照上面的List调集声明一个简单的枚举器

(这个枚举器,只是为了简单的说明一下问题)

public class GameMoves { private IEnumerator cross; private IEnumerator circle; public GameMoves() { cross = Cross(); circle = Circle(); } private int move = 0; const int MaxMoves = 9; public IEnumerator Cross() { while (true) { Console.WriteLine("Cross, move {0}", move); if (++move >= MaxMoves) { yield break; } yield return circle; } } public IEnumerator Circle() { while (true) { Console.WriteLine("Circle,move{0}",move); if (++move>=MaxMoves) { yield break; } yield return cross; } } }

View Code

重写一下Main要领

var game = new GameMoves(); //将枚举器设置为由game.Cross()返回的枚举器类型 IEnumerator enumerator = game.Cross(); //第一次挪用 MoveNext()时,会挪用Cross()要领,Cross()要领使用yield返回另一个枚举器 while (enumerator.MoveNext()) { //返回的值可以用Current属性访谒,并设置为enumerator变量,用于下一次循环 enumerator = enumerator.Current as IEnumerator; }

View Code

通过上面的例子我们能看出使用while来变向说明foreach的内部执行方法。

通过 foreach 语句或 LINQ 盘问来使用迭代器要领。