什么时候可以使用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);
}
}

它的输出结果:

接下来,我们使用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 = ;
const int MaxMoves = ;
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;
}
}
}

重写一下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;
}

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

通过 foreach 语句或 LINQ 查询来使用迭代器方法。

foreach 循环的每次迭代都会调用迭代器方法。 迭代器方法运行到 yield return 语句时,会返回一个 expression,并保留当前在代码中的位置。 下次调用迭代器函数时,将从该位置重新开始执行。

(部分源自msdn)

C#基础知识 yield与foreach的更多相关文章

  1. C#基础知识---迭代器与Foreach语句

    一.Foreach语句简介 在C# 1.0中我们经常使用foreach来遍历一个集合中的元素,然而如果一个集合要支持使用foreach语句来进行遍历,这个集合一般需要IEnumerable或IEnum ...

  2. C# 基础知识总结

    要学好C#,基础知识的重要性不言而喻,现将常用到的一些基础进行总结,总结如下: 1. 数据类型转换: 强制类型转换(Chart--> int):  char cr='A';   int i = ...

  3. Java 基础知识总结

    作者QQ:1095737364    QQ群:123300273     欢迎加入! 1.数据类型:  数据类型:1>.基本数据类型:1).数值型: 1}.整型类型(byte  8位   (by ...

  4. Java基础知识总结(超级经典)

    Java基础知识总结(超级经典) 写代码: 1,明确需求.我要做什么? 2,分析思路.我要怎么做?1,2,3. 3,确定步骤.每一个思路部分用到哪些语句,方法,和对象. 4,代码实现.用具体的java ...

  5. 毕向东—Java基础知识总结(超级经典)

    Java基础知识总结(超级经典) 写代码: 1,明确需求.我要做什么? 2,分析思路.我要怎么做?1,2,3. 3,确定步骤.每一个思路部分用到哪些语句,方法,和对象. 4,代码实现.用具体的java ...

  6. C#基础知识汇总(不断更新中)

    ------------------------------目录---------------------------- 1.隐式类型2.匿名类型3.自动属性4.初始化器5.委托6.泛型7.泛型委托8 ...

  7. Java 基础知识总结1

    作者QQ:1095737364    QQ群:123300273     欢迎加入! 1.数据类型:  数据类型:1>.基本数据类型:1).数值型: 1}.整型类型(byte  8位   (by ...

  8. Linq的简介和基础知识学习

    学习LINQ之前,我们要知道LINQ是干什么,解决什么问题的,怎样学习? 一.LINQ简介 1.什么是LINQ? 什么是LINQ?LINQ中文翻译为语言集成查询(Language Integrated ...

  9. 黑马毕向东Java基础知识总结

    Java基础知识总结(超级经典) 转自:百度文库 黑马毕向东JAVA基础总结笔记    侵删! 写代码: 1,明确需求.我要做什么? 2,分析思路.我要怎么做?1,2,3. 3,确定步骤.每一个思路部 ...

随机推荐

  1. day2--SecureCRT的配置

    生产中,我们是看不到虚拟机的工作界面,虚拟机的界面相当于机房显示屏的样子,实际上我们是在操作工具里面进行管理,这里使用SecureCRT远程连接虚拟机,SecureCRT的设置如下: 1.打开Secu ...

  2. Anaconda快捷搭建Python2和Python3环境

    我们在使用Pycharm编辑Python程序经常会因为不熟悉Python2和Python3的一些代码区别而导致错误,我们知道他们之间很多代码是必须运行在对应版本中的,否则是会报错的.因此,本文介绍一个 ...

  3. Mac上查看隐藏文件夹/文件

    一.查看隐藏文件夹: 可以直接在终端执行 open ~/文件夹名称 如: open ~/.ssh 二.查看隐藏文件: 在Finder下进入你想要操作的文件夹,按快捷键Command + F 调出搜索窗 ...

  4. Nodejs前端服务器压缩图片

    Nodejs作为前端服务器,自然能承担处理图片的能力, 使用GM for nodejs 作为图片处理器,调用ImageMagick处理图片 使用ImageMagick var imageMagick ...

  5. [转载] PHP工作模型与运行机制

    转载自http://www.nowamagic.net/librarys/veda/detail/350 PHP的工作模型非常特殊.从某种程度上说,PHP和ASP.ASP.NET.JSP/Servle ...

  6. 【转】Linux下软、硬链接的创建和删除

    原文:http://www.cnblogs.com/xiaochaohuashengmi/archive/2011/10/05/2199534.html 在Linux系统中,内核为每一个新创建的文件分 ...

  7. SDRAM操作(FPGA实现)

    对SDRAM基本概念的介绍以及芯片手册说明,请参考上一篇文章SDRAM操作说明. 1. 说明 如图所示为状态机的简化图示,过程大概可以描述为:SDRAM(IS42S16320D)上电初始化完成后,进入 ...

  8. pyqt5实现打开子窗口

    # -*- coding: utf-8 -*- import sys from PyQt5.QtWidgets import * from PyQt5.QtCore import * class Fi ...

  9. Entity Framework——常见报错总结

    1 实体属性配置为IsRequired()对更新的影响 抛出异常类型DbEntityValidationException 表结构: 实体: public class User { public in ...

  10. WebVR认识

    什么是WebVR WebVR是一种开放标准,可以在浏览器中体验VR,目标是让每个人都能轻松进入虚拟现实体验.