C#基础知识 yield与foreach
什么时候可以使用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的更多相关文章
- C#基础知识---迭代器与Foreach语句
一.Foreach语句简介 在C# 1.0中我们经常使用foreach来遍历一个集合中的元素,然而如果一个集合要支持使用foreach语句来进行遍历,这个集合一般需要IEnumerable或IEnum ...
- C# 基础知识总结
要学好C#,基础知识的重要性不言而喻,现将常用到的一些基础进行总结,总结如下: 1. 数据类型转换: 强制类型转换(Chart--> int): char cr='A'; int i = ...
- Java 基础知识总结
作者QQ:1095737364 QQ群:123300273 欢迎加入! 1.数据类型: 数据类型:1>.基本数据类型:1).数值型: 1}.整型类型(byte 8位 (by ...
- Java基础知识总结(超级经典)
Java基础知识总结(超级经典) 写代码: 1,明确需求.我要做什么? 2,分析思路.我要怎么做?1,2,3. 3,确定步骤.每一个思路部分用到哪些语句,方法,和对象. 4,代码实现.用具体的java ...
- 毕向东—Java基础知识总结(超级经典)
Java基础知识总结(超级经典) 写代码: 1,明确需求.我要做什么? 2,分析思路.我要怎么做?1,2,3. 3,确定步骤.每一个思路部分用到哪些语句,方法,和对象. 4,代码实现.用具体的java ...
- C#基础知识汇总(不断更新中)
------------------------------目录---------------------------- 1.隐式类型2.匿名类型3.自动属性4.初始化器5.委托6.泛型7.泛型委托8 ...
- Java 基础知识总结1
作者QQ:1095737364 QQ群:123300273 欢迎加入! 1.数据类型: 数据类型:1>.基本数据类型:1).数值型: 1}.整型类型(byte 8位 (by ...
- Linq的简介和基础知识学习
学习LINQ之前,我们要知道LINQ是干什么,解决什么问题的,怎样学习? 一.LINQ简介 1.什么是LINQ? 什么是LINQ?LINQ中文翻译为语言集成查询(Language Integrated ...
- 黑马毕向东Java基础知识总结
Java基础知识总结(超级经典) 转自:百度文库 黑马毕向东JAVA基础总结笔记 侵删! 写代码: 1,明确需求.我要做什么? 2,分析思路.我要怎么做?1,2,3. 3,确定步骤.每一个思路部 ...
随机推荐
- 身为运维的你,怎么掌握python才不会失业
以前,我们都说Python是运维工程师的未来:现在,为什么大家都说不会Python的运维都将失业?运维必须懂开发,特别是python开发,已经形成大家的共识,不懂开发的运维,路会越走越窄. 而现在的情 ...
- ListView中点击Item没有任何响应
不多说,上代码:如下图 红色方框的东西, android:descendantFocusability=”blocksDescendants” 如果不添加的话,在android的8.0手机上点击没有响 ...
- 阿里云CentOS搭建系统
1.在阿里云网站上购买申请服务器. 2.通过Xshell连接服务器,并用root账户登入. 3.配置java开发环境:(也可以使用阿里云一键部署,自动配置并部署服务器) 一.安装jdk 1.查看Lin ...
- 8. 理解ZooKeeper的内部工作原理
到目前为止,我们已经讨论了ZooKeeper服务的基础知识,并详细了解了数据模型及其属性. 我们也熟悉了ZooKeeper 监视(watch)的概念,监视就是在ZooKeeper命名空间中的znode ...
- [转载] ConcurrentHashMap原理分析
转载自http://blog.csdn.net/liuzhengkang/article/details/2916620 集合是编程中最常用的数据结构.而谈到并发,几乎总是离不开集合这类高级数据结构的 ...
- ANDROID基础ACTIVITY篇之Activity的生命周期(一)
首先我们先来看一下官方的Android的生命周期图: 根据这个流程图我们可以看到Activity的生命周期一共有7个方法,那么接下来我们就来聊聊这些方法执行过程. 首先在两个Activity(Main ...
- 激光相机数据融合(4)--KITTI数据集中matlab接口说明及扩展
KITTI数据集接口已经提供了matlab接口,本篇将说明详细说明其应用并与PCL进行对接.PCL为C++点云处理语言库,详情可见:http://pointclouds.org/ 程序可以从官网下载, ...
- Chapter 8: Exceptional Control Flow
概述: 我们可以用一种“流”的概念来理解处理器的工作流程,PC(Program Counter)依次为a0,a1,a2,...,an-1,这个序列可以称作control flow.当然我们并不总是按顺 ...
- 我的第一个python web开发框架(17)——产品管理
这是后台管理系统最后一个功能,产品管理,它的接口与页面功能与上一章差不多. 获取产品列表接口 @get('/api/product/') def callback(): ""&qu ...
- deepin 常用设置
1 不开特效和动画,开启透明无黑边 #!/bin/bash #开启 metacity 窗管合成,取代正在运行的窗管 deepin-metacity --composite --replace #关闭 ...