C#枚举器:foreach语句、IEnumerable、IEnumerator以及yield return (一)
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 (一)相关推荐
- ICollection IEnumerable/IEnumerator IDictionaryEnumerator yield
Enumerable和IEnumerator接口是.NET中非常重要的接口,二者区别: 1. IEnumerable是个声明式的接口,声明实现该接口的类就是"可迭代的enumerable&q ...
- C#图解教程 第十八章 枚举器和迭代器
枚举器和迭代器 枚举器和可枚举类型 第12章中,我们看到可以用foreach语句遍历数组.在本章,我们会进一步探讨数组,来看看为什么它们可以被foreach语句处理.我们还会研究如何使用迭代器为用户自 ...
- C# IEnumerator枚举器
1.对象只要一个类型实现了IEnumerable接口就能遍历 2.IEnumerator是枚举器,一个接口类,实现MoveNext->Current->Reset 3.yield关键字是一 ...
- 一文详解枚举器和迭代器!
作者 | 喵叔 责编 | 胡巍巍 出品 | 程序人生(ID:coder_life) 今天来讲解一下开发人员会用但不理解的C#中的知识,这篇文章我们讲解一下枚举器与迭代器的知识. 枚举器 什么是枚举器? ...
- 黑马程序猿——C#枚举器深入解析
------- Java培训.Android培训.iOS培训..Net培训 .期待与您交流! ------- 废话不说了,上码,如果你可以一眼看穿下面这段代码的执行流程,请您就飘过吧(这段代码摘抄自 ...
- foreach遍历进阶_“枚举器“/GetEnumerator()方法
通过foreach遍历数据,实际上是调用了一个"枚举器"来遍历数据,和foreach没有任何关系,foreach只是语法上的简化而已,或者说foreach语句降低了枚举的复杂度. ...
- foreach和IEnumerable+yield和IEnumerator
C#里,foreach可以算是个高一等级的循环,因为想要使用foreach必须实现IEnumberable,然后还需要在这个接口的唯一方法中,用yield return返回元素,才能达到foreach ...
- C#学习之用迭代器实现枚举器
上一篇文章为自定义类实现了foreach的功能,但实现过程中要实现IEnumerator接口(包括MoveNext.Reset函数和Current属性)以便GetEnumerator函数能获取枚举数, ...
- 基础【循环】-----(枚举器)------(转)
Iterator:枚举器 如果你正在创建一个表现和行为都类似于集合的类,允许类的用户使用foreach语句对集合中的成员进行枚举将会是很方便的.这在C# 2.0中比 C# 1.1更容易实现一些.作为演 ...
- IEnumerator/ IEnumerable/ yield return/ StartCoroutine 详解
Update逻辑 IEnumerator/ IEnumerable public interface IEnumerable { IEnumerator GetEnumerator(); } publ ...
最新文章
- 【项目管理】聊聊项目管理几点实践和理解(1)
- java设计模式_工厂方法
- 同IP不同端口Session冲突问题
- windows服务autofac注入quartz任务
- java 集成 kafka 0.8.2.1 适配jdk1.6
- 初二因式分解奥数竞赛题_八年级数学因式分解专项练习试题.doc
- 报告分享】2020年汽车行业直播研究报告.pdf(附下载链接)
- Java中一个逐渐被遗忘的强大功能,强到你难以置信!
- 解决:Failed to create 'build\outputs\apk\watch-debug-unaligned.apks': 拒绝访问。
- 异贝,通过移动互联网技术,为中小微实体企业联盟、线上链接、线上线下自定义营销方案推送。案例32
- 20000个游戏娱乐音效素材库
- RFID医疗废物管理系统解决方案-RFID技术的医疗废弃物管理系统
- 360度全景视频html,360度全景视频是怎么拍摄出来的?
- 计算机制作贺卡教案,三八爱心节贺卡教案
- 无线攻击 --aircrack-ng套件之一:Airbase-ng(攻击客户端多用途工具)
- 计算机二级真题期刊论文模板,论文格式?二级标题是什么?
- 名帖13 邓石如 篆书《白氏草堂记》六条屏
- 计算机体系-指令系统
- 我的世界神奇宝贝服务器怎么修改6v,我的世界神奇宝贝改6v | 手游网游页游攻略大全...
- 在存储过程中的clob数据类型
热门文章
- python中访问lmdb
- 用科学数据求真:月球的激光发射器有用吗?
- new和delete运算符
- laravel 任务队列_Laravel 队列系统实现及使用教程
- winform 实现qq代理_「设计模式」代理模式:神奇的代理模式,节省了我80%开发时间...
- python保存数组到txt_np.savetxt()——将array保存到txt文件,并保持原格式
- c语言三位数倒序,C语言求助!一个三位数的逆序数,总是编不对
- python生成json文件_json文件生成by python
- 隐马尔可夫模型python_机器学习中的隐马尔科夫模型(HMM)详解
- python矩阵运算_python 矩阵运算