对[foreach]的浅究到发现[yield]
闲来无事,翻了翻以前的代码,做点总结,菜鸟从这里起航,呵呵。
一、List的foreach遍历
先上代码段[1]:
class Program
{
static void Main(string[] args)
{
List<string> dayList = new List<string> { "Sun", "Mon", "Tue", "Wed", "Thr", "Fri", "Sat" };
foreach (var day in dayList)
{
Console.WriteLine(day);
}
Console.ReadKey();
}
}
这是我们经常用的,简单明了,这里就不赘述了。
二、对List的浅究
接着我就产生了疑问,List具有怎样的特性才使得foreach可以对它进行遍历呢?这个遍历是如何实现的?
下面就来浅究,再上代码段[2]:
public class DaysList<T> : System.Collections.IEnumerable
{
T[] daysArry;
public DaysList(T[] days)
{
daysArry = days;
}
public System.Collections.IEnumerator GetEnumerator()
{
for (int i = ; i < daysArry.Length; i++)
{
yield return daysArry[i];
}
}
} class Program
{
static void Main(string[] args)
{
string[] days = { "Sun", "Mon", "Tue", "Wed", "Thr", "Fri", "Sat" };
var daysList = new DaysList<string>(days); foreach (string day in daysList)
{
System.Console.WriteLine(day);
}
Console.ReadKey();
}
}
通过查阅我们发现LIst是通过实现System.Collections.IEnumerable接口来达到可以被遍历的能力,而实现System.Collections.IEnumerable接口必须实现它里面的GetEnumerator()方法,用来返回一个循环访问集合的枚举器,代码段[2]中就有我对GetEnumerator()方法的实现,其中有个关键字[yield]不知大家注意到没。
我的理解是:与其说是foreach遍历List,不如说是foreach遍历的是List中的GetEnumerator()方法返回的枚举器,注意这个枚举器实现了IEnumerator 接口,(插句话,IEnumerable接口标识某个类具备被遍历的能力,而IEnumerator 接口则使某个类真正具备这个能力!)。而当foreach对List进行循环遍历时,每个循环就是通过[yield]来分隔的。
三、对foreach的浅究
通过标题二,我们大概对List进行了了解,但不清楚,下面看看foreach。
依旧代码段[3]:
//注意:其中类DaysList<T>的实现同代码段[2]一样
//这里只展示foreach的实现。
class Program
{
static void Main(string[] args)
{
string[] days = { "Sun", "Mon", "Tue", "Wed", "Thr", "Fri", "Sat" };
var daysList = new DaysList<string>(days); System.Collections.IEnumerator enumertor = daysList.GetEnumerator();
while (enumertor.MoveNext())
{
System.Console.WriteLine(enumertor.Current);
}
Console.ReadLine();
}
}
就像上面说的,foreach其实遍历的是List中的GetEnumerator()方法返回的枚举器enumertor,而这个枚举器所实现的接口IEnumerator中定义了只读的Current属性(用来获取枚举器当前的所指的集合中的元素)、MoveNext方法(将枚举器推进到集合中的下一个元素,返回值代表是否到了集合末尾)、Reset方法(使枚举器指到集合第一个元素之前,也就是重置枚举器),明白了这些,我们就可以像代码段[3]中一样通过[while]语法来实现跟foreach一样的功能了,而上文中的[yield]关键字浅显的理解就是用来划分要遍历的集合中的每个元素的。
最后,本来还想分析分析这个实现了IEnumerator接口的枚举器是怎么生成的,想象一下它的内部实现,应该很有意思!
就这样吧,下班了,大家共勉!
对[foreach]的浅究到发现[yield]的更多相关文章
- 对[yield]的浅究到发现[async][await]
原文:对[yield]的浅究到发现[async][await] 上篇对[foreach]的浅究到发现[yield]写完后,觉得对[yield]还没有理解清楚,想起曾经看过一位大牛的帖子讲的很深刻(链接 ...
- 【Python学习笔记之二】浅谈Python的yield用法
在上篇[Python学习笔记之一]Python关键字及其总结中我提到了yield,本篇文章我将会重点说明yield的用法 在介绍yield前有必要先说明下Python中的迭代器(iterator)和生 ...
- 字典查找、linq、foreach、yield等几种查找性能对比
先上代码,以1千万记录的内存查找测试: List<Student> stuList = new List<Student>(); Dictionary<int, Stud ...
- C# 中yield关键字解析
前言 前段时间了解到yield关键字,一直觉得还不错.今天给大家分享一下yield关键字的用法.yield return 返回集合不是一次性返回所有集合元素,而是一次调用返回一个元素.具体如何使用yi ...
- C# yield return 原理探究
天需要些一个小工具,需要使用到多线程读写程序集,接口方法返回值类型需要为"IEnumerable<string>"这里用到了"yield return&quo ...
- Python 生成器与迭代器 yield 案例分析
前几天刚开始看 Python ,后因为项目突然到来,导致Python的学习搁置了几天.然后今天看回Python 发现 Yield 这个忽然想不起是干嘛用的了(所以,好记性不如烂笔头.).然后只能 花点 ...
- 浅谈inline-block
一.区分block,inline,inline-block 1.block block元素会独占一行,多个block元素会各自新起一行.默认情况下,block元素宽度自动填满其父元素宽度. block ...
- forEach循环对集合进行循环时,需判断是否为null;
分析forEach的源码会发现:foreach源码例子: public class Foreach { public static void main(String[] args) { List< ...
- List<T>.ForEach 调用异步方法的意外
有这么个异步方法 private static async Task<int> Compute(int s) { return await Task<int>.Run(() = ...
随机推荐
- linuxIO刷新机制fsync和fdatasync详细解释
前言: Linux,unix在内核中设有 缓冲区快速缓冲或页面快速缓冲.大多数磁盘I/O都通过缓冲进行,採用延迟写技术. sync:将全部改动过的快缓存区排入写队列.然后返回.并不等待实际写磁盘操作结 ...
- 玩转Web之JavaScript(二)-----javaScript语法总结(二) 涉及Date与数组的语法
Date: document.write(document.lastModified) 网页最后一次更新时间 a=new Date(); //创建 a 为一个新的时期象 y=a.getY ear( ...
- 大约session_cached_cursors在不同的db在默认不同的版本号
大约session_cached_cursors的值,不同db版本号具有不同的默认值: 9i是 0 10.1 0 10.2 是20 11.1 是50 11.2 是50 12.1 是50 值值得注意的是 ...
- 运行safari提示:无法启动此程序,因为计算机中丢失 QTCF.dll
解决办法: 1.去百度搜索“QTCF.dll”,找到一个靠谱的下载地址获取到该dll文件: 2.将文件放到 安装目录:Safari\Apple Application Support 下边.
- HDD-FAT32 ZIP-FAT32
在使用U当家U盘启动盘制作工具的时候会看到一个模式的选项,模式分为HDD-FAT32和ZIP-FAT32两个常用的模式,其它的模式几乎用不到的.那么HDD-FAT32和ZIP-FAT32模式到底有什么 ...
- W3C DOM 事件模型(简述)
1.事件模型 由于事件捕获与冒泡模型都有其长处和解释,DOM标准支持捕获型与冒泡型,能够说是它们两者的结合体.它能够在一个DOM元素上绑定多个事件处理器,而且在处理函数内部,thiskeyword仍然 ...
- 播放视频的框架Vitamio的使用问题
曾经用过这个牛逼的框架,后来又任意搞了下.发现播放不了视频了.搞了老半天才搞好,今天又随便整了下,发现又不行了.我勒个插! 如今最终又搞出来了,发现我总是把步骤搞错或少写了些东西 总的步骤: 一:导入 ...
- windows 10 install oracle 12c error:[ INS-30131 ]
"[ INS-30131 ] the Initial Setup That Is Required to Run the Installation Program Validation Wa ...
- Mozilla 构建系统(转)
英文来源:Mozilla’s Build System 中文出处:开放博客,由灰狐翻译小组制作 Mozilla 构建系统是一个非常酷的分布式系统,运行在BuildBot上.系统能在每次修改后自动重新构 ...
- 王立平--android特权
//同意应用程序访问和更改checkin数据库"properties"数据表 android.permission.ACCESS_CHECKIN_PROPERTIES //同意应用 ...