using System;
using System.Collections;

C#中,我们通常可以用foreach语句来遍历数组或集合,下面深入探讨一下其工作原理

①自定义集合MyList

为了说明使用IEnumerable和IEnumerator接口,从而让数组或集合支持foreach语句的原理,我们首先自定义一个简单的链表形集合MyList,其中仅实现了AddData方法,其他相关方法没有写出,代码如下:

//集合包含的项,即所谓的节点
public class DataItem
{public DataItem Next { get; set; }public object Data { get; set; }public DataItem(object data){this.Data = data;}
}
//自定义集合类
public class MyList
{public DataItem FirstItem { get; set; }public DataItem LastItem { get; set; }public void AddData(object data){DataItem newItem = new DataItem(data);if (this.FirstItem == null){this.FirstItem = newItem;this.LastItem = newItem;}else{this.LastItem.Next = newItem;this.LastItem = newItem;}}
}

②IEnumerable接口

foreach在遍历集合的时候,实质上调用的是GetEnumerator方法,因此要使得集合支持foreach遍历,必须实现GetEnumerator方法,该方法定义在IEnumerable接口中,该接口定义如下:

public interface IEnumerable
{IEnumerator GetEnumerator();
}

③IEmunerator接口

因此只要让MyList继承IEnumerable接口,并实现GetEnumerator方法即可,可是该方法要求返回一个IEnumerator,现在我们还没任何地方实现这个IEmunerator接口,因此我们先来看看他的定义

public interface IEnumerator
{//集合中的当前元素。object Current { get; }//如果枚举数成功地推进到下一个元素,则为 true;如果枚举数越过集合的结尾,则为 false。bool MoveNext();//将枚举数设置为其初始位置,该位置位于集合中第一个元素之前。void Reset();
}

④实现IEnumerator接口

从该接口的定义可以看出,foreach语句就是根据MoveNext方法和Current属性,一个一个遍历集合元素的,为了使得思路清晰,这里我们单独编写一个类来实现该接口,且该类会以上面的MyList为基础,以便MyList调用它

public class MyEnumerator:IEnumerator
{private DataItem currentItem = new DataItem(null);public MyEnumerator (MyList list) //使用MyList的实例来构造该类{this.currentItem.Next = list.FirstItem;}public object Current{get { return currentItem.Data; }}public bool MoveNext(){if(currentItem.Next != null){currentItem = currentItem.Next;return true;}else{return false;}}public void Reset(){throw new NotImplementedException();}
}

⑤实现IEnumerable接口

有了这个MyEnumerator后,就可以让MyList实现IEnumerable接口中的GetEnumerator方法了,向MyList中添加如下代码

public IEnumerator GetEnumerator()
{return new MyEnumerator(this);
}

到此为止,虽然MyList的功能还十分不完善,但已经支持foreach语句遍历了,需要说明一点的是,不论MyList是否继承接口IEnumerable,只要实现了GetEnumerator方法,就可以支持foreach语句。

⑥yield return

上面整个过程对于演示foreach语句的原理相当有用,不过每次都这样去实现就太费劲了,C#中可以使用yield return语句来帮我们自动实现IEnumerator接口,一下使得工作轻松多了,对MyList中的GetEnumerator方法作如下修改即可抛弃繁琐的MyEnumerator了

public IEnumerator GetEnumerator()
{//return new MyEnumerator(this);DataItem curent = this.FirstItem;while(curent != null){yield return curent.Data;curent = curent.Next;}
}

转载于:https://www.cnblogs.com/ArtofDesign/p/3612492.html

C#枚举器:foreach语句、IEnumerable、IEnumerator以及yield return (一)相关推荐

  1. ICollection IEnumerable/IEnumerator IDictionaryEnumerator yield

    Enumerable和IEnumerator接口是.NET中非常重要的接口,二者区别: 1. IEnumerable是个声明式的接口,声明实现该接口的类就是"可迭代的enumerable&q ...

  2. C#图解教程 第十八章 枚举器和迭代器

    枚举器和迭代器 枚举器和可枚举类型 第12章中,我们看到可以用foreach语句遍历数组.在本章,我们会进一步探讨数组,来看看为什么它们可以被foreach语句处理.我们还会研究如何使用迭代器为用户自 ...

  3. C# IEnumerator枚举器

    1.对象只要一个类型实现了IEnumerable接口就能遍历 2.IEnumerator是枚举器,一个接口类,实现MoveNext->Current->Reset 3.yield关键字是一 ...

  4. 一文详解枚举器和迭代器!

    作者 | 喵叔 责编 | 胡巍巍 出品 | 程序人生(ID:coder_life) 今天来讲解一下开发人员会用但不理解的C#中的知识,这篇文章我们讲解一下枚举器与迭代器的知识. 枚举器 什么是枚举器? ...

  5. 黑马程序猿——C#枚举器深入解析

    ------- Java培训.Android培训.iOS培训..Net培训 .期待与您交流!  ------- 废话不说了,上码,如果你可以一眼看穿下面这段代码的执行流程,请您就飘过吧(这段代码摘抄自 ...

  6. foreach遍历进阶_“枚举器“/GetEnumerator()方法

    通过foreach遍历数据,实际上是调用了一个"枚举器"来遍历数据,和foreach没有任何关系,foreach只是语法上的简化而已,或者说foreach语句降低了枚举的复杂度. ...

  7. foreach和IEnumerable+yield和IEnumerator

    C#里,foreach可以算是个高一等级的循环,因为想要使用foreach必须实现IEnumberable,然后还需要在这个接口的唯一方法中,用yield return返回元素,才能达到foreach ...

  8. C#学习之用迭代器实现枚举器

    上一篇文章为自定义类实现了foreach的功能,但实现过程中要实现IEnumerator接口(包括MoveNext.Reset函数和Current属性)以便GetEnumerator函数能获取枚举数, ...

  9. 基础【循环】-----(枚举器)------(转)

    Iterator:枚举器 如果你正在创建一个表现和行为都类似于集合的类,允许类的用户使用foreach语句对集合中的成员进行枚举将会是很方便的.这在C# 2.0中比 C# 1.1更容易实现一些.作为演 ...

  10. IEnumerator/ IEnumerable/ yield return/ StartCoroutine 详解

    Update逻辑 IEnumerator/ IEnumerable public interface IEnumerable { IEnumerator GetEnumerator(); } publ ...

最新文章

  1. 【项目管理】聊聊项目管理几点实践和理解(1)
  2. java设计模式_工厂方法
  3. 同IP不同端口Session冲突问题
  4. windows服务autofac注入quartz任务
  5. java 集成 kafka 0.8.2.1 适配jdk1.6
  6. 初二因式分解奥数竞赛题_八年级数学因式分解专项练习试题.doc
  7. 报告分享】2020年汽车行业直播研究报告.pdf(附下载链接)
  8. Java中一个逐渐被遗忘的强大功能,强到你难以置信!
  9. 解决:Failed to create 'build\outputs\apk\watch-debug-unaligned.apks': 拒绝访问。
  10. 异贝,通过移动互联网技术,为中小微实体企业联盟、线上链接、线上线下自定义营销方案推送。案例32
  11. 20000个游戏娱乐音效素材库
  12. RFID医疗废物管理系统解决方案-RFID技术的医疗废弃物管理系统
  13. 360度全景视频html,360度全景视频是怎么拍摄出来的?
  14. 计算机制作贺卡教案,三八爱心节贺卡教案
  15. 无线攻击 --aircrack-ng套件之一:Airbase-ng(攻击客户端多用途工具)
  16. 计算机二级真题期刊论文模板,论文格式?二级标题是什么?
  17. 名帖13 邓石如 篆书《白氏草堂记》六条屏
  18. 计算机体系-指令系统
  19. 我的世界神奇宝贝服务器怎么修改6v,我的世界神奇宝贝改6v | 手游网游页游攻略大全...
  20. 在存储过程中的clob数据类型

热门文章

  1. python中访问lmdb
  2. 用科学数据求真:月球的激光发射器有用吗?
  3. new和delete运算符
  4. laravel 任务队列_Laravel 队列系统实现及使用教程
  5. winform 实现qq代理_「设计模式」代理模式:神奇的代理模式,节省了我80%开发时间...
  6. python保存数组到txt_np.savetxt()——将array保存到txt文件,并保持原格式
  7. c语言三位数倒序,C语言求助!一个三位数的逆序数,总是编不对
  8. python生成json文件_json文件生成by python
  9. 隐马尔可夫模型python_机器学习中的隐马尔科夫模型(HMM)详解
  10. python矩阵运算_python 矩阵运算