原文:对[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]的更多相关文章

  1. 对[yield]的浅究到发现[async][await]

    原文:对[yield]的浅究到发现[async][await] 上篇对[foreach]的浅究到发现[yield]写完后,觉得对[yield]还没有理解清楚,想起曾经看过一位大牛的帖子讲的很深刻(链接 ...

  2. 【Python学习笔记之二】浅谈Python的yield用法

    在上篇[Python学习笔记之一]Python关键字及其总结中我提到了yield,本篇文章我将会重点说明yield的用法 在介绍yield前有必要先说明下Python中的迭代器(iterator)和生 ...

  3. 字典查找、linq、foreach、yield等几种查找性能对比

    先上代码,以1千万记录的内存查找测试: List<Student> stuList = new List<Student>(); Dictionary<int, Stud ...

  4. C# 中yield关键字解析

    前言 前段时间了解到yield关键字,一直觉得还不错.今天给大家分享一下yield关键字的用法.yield return 返回集合不是一次性返回所有集合元素,而是一次调用返回一个元素.具体如何使用yi ...

  5. C# yield return 原理探究

    天需要些一个小工具,需要使用到多线程读写程序集,接口方法返回值类型需要为"IEnumerable<string>"这里用到了"yield return&quo ...

  6. Python 生成器与迭代器 yield 案例分析

    前几天刚开始看 Python ,后因为项目突然到来,导致Python的学习搁置了几天.然后今天看回Python 发现 Yield 这个忽然想不起是干嘛用的了(所以,好记性不如烂笔头.).然后只能 花点 ...

  7. 浅谈inline-block

    一.区分block,inline,inline-block 1.block block元素会独占一行,多个block元素会各自新起一行.默认情况下,block元素宽度自动填满其父元素宽度. block ...

  8. forEach循环对集合进行循环时,需判断是否为null;

    分析forEach的源码会发现:foreach源码例子: public class Foreach { public static void main(String[] args) { List< ...

  9. List<T>.ForEach 调用异步方法的意外

    有这么个异步方法 private static async Task<int> Compute(int s) { return await Task<int>.Run(() = ...

随机推荐

  1. IOS基金会_ UICollectionView简单易用

    和表格视图类似 UICollectionView的使用有两种方法 一种是继承UICollectionViewController,这个Controller会自带一个UICollectionView. ...

  2. Codeforces 451E Devu and Flowers(容斥原理)

    题目链接:Codeforces 451E Devu and Flowers 题目大意:有n个花坛.要选s支花,每一个花坛有f[i]支花.同一个花坛的花颜色同样,不同花坛的花颜色不同,问说能够有多少种组 ...

  3. 浅析MVC和说媒的过程

    什么是MVC? MVC 全名是Model View Controller,是模型(model)-视图(view)-控制器(controller)的缩写,一种软件设计典范,用一种业务逻辑.数据.界面 显 ...

  4. Oracle批量执行脚本文件

    以下是Oracle批量执行脚本文件的步骤和方法 1.创建脚本文件(xx.sql): 例如文件CreateTable Create table tb1( id varchar2(30), Name va ...

  5. 5、Cocos2dx 3.0小游戏开发的例子寻找测试三个简单的介绍和总结

    繁重的劳动开发商,当转载请注明出处:http://blog.csdn.net/haomengzhu/article/details/27186557 測试例子简单介绍 Cocos2d-x 为我们提供了 ...

  6. HDU3988-Harry Potter and the Hide Story(数论-质因数分解)

    Harry Potter and the Hide Story Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/65536 ...

  7. AndroidSlidingUpPanel 使用控制和简单的分析方法

    滑 - 向上的时间可以飞起来控件的显示区域.分类似至play music有效. 该控件在主界面中有一个例如以下图红色箭头所指的底部触发区域: 该区域点击的时候被隐藏在下方的内容将网上漂移到顶部,直到被 ...

  8. 示例:Netty 处理 TCP数据分包协议

    一个.Netty解决TCP协议的数据分包的想法 我们知道通过TCP协议发送接收数据时,假设数据过大.接收到的数据会是分包的.比方:                                   ...

  9. Webpact打包React后端Node+Express

    Webpact打包React后端Node+Express 前言 React官方推荐用Browserify或者Webpack 来开发React组件. Webpack 是什么?是德国开发者 Tobias ...

  10. android 渐变drawable

    渐变Drawable它是使用<gradient>的标记的形状Drawable定义子节点的定义. 每个梯度Drawable求至少要有一个startColor和endColor属性,而且支持一 ...