迭代器模式(Iterator),提供一种方法顺序访问一个聚合对象中的各种元素,而又不暴露该对象的内部表示。C#中使用IEnumerator接口实现,Java中使用Iterator接口实现,其中原理都差不多,下面我就用C#代码来演示下迭代器的实现。
假如我要实现一个自定义容器列表,就叫它SpecialList吧,可以实现类似ArrayList的功能。如下:
这个时候我想遍历这个列表,当我使用foreach的时候,报错了。如下:
提示SpecialList不包含GetEnumerator的公共实例定义,在C#中,如果想要使用foreach遍历列表对象,这个列表对象必须要实现IEnumerable的GetEnumerator()方法,我们来加一下。如下:
继承后,foreach列表的时候就不会再报错了,但我们并没有实现GetEnumerator()这个方法。我们看一下这个方法的返回值类型为IEumerator,F12进去看一下这个接口的定义。如下:
这个接口里面有两个方法和一个属性。其中MoveNext()是最核心的方法,就是在这个里面实现列表的遍历。话不多说,我们先定义一个继承IEnumerator的类,就叫SpecialEnumerator吧。如下:
不好意思,我已经简单的写好这个类了,那就简单的讲一个这个类的原理吧。SpecialEnumerator主要定义了一个SpecialList类型的_list,还有当前元素的_current,还有当前索引的_index。我们重点看一下MoveNext方法,里面的代码其实也非常简单,就是判断_index是否已经到底,没有的话叫取出当前_index上的元素赋予_cuurent,然后返回true,这里的返回值给到foreach,如果为true,则继续遍历,如果为false,则foreach跳出循环。我们再来看一下SpecialList中怎么使用SpecialEnumerator类。如下:
这样只是返回SpecialEnumerator的一个实例,同时将当前要枚举的列表对象(this)传入进去。
你可能会有疑问,这里只是返回一个对象,在foreach中并没有循环判断MoveNext是true还是false的代码,那它是怎么实现的呢?其实foreach只是一个语法糖,它本质上其实是使用了while语法来实现的。如下:
到这里,相信大家已经明白迭代器是怎么实现的了。最后再补充一下,大家可能会觉得额外实现SpecialEnumerator类比较繁琐,其实如果你的列表遍历规则比较简单的话,可以使用yield语法来代替SpecialEnumerator类,只要这样写就行。如下:
但如果你的列表遍历规则比较特殊,比如像栈、队列这样的容器类时,还是建议实现枚举类,这样可以将遍历规则封装在MoveNext中。
 
感谢阅读,如果觉得不错,给个【推荐】吧!
 
 
更多精彩内容,可关注我的公众号:
 

C#实现迭代器的更多相关文章

  1. 匹夫细说C#:庖丁解牛迭代器,那些藏在幕后的秘密

    0x00 前言 在匹夫的上一篇文章<匹夫细说C#:不是“栈类型”的值类型,从生命周期聊存储位置>的最后,匹夫以总结和后记的方式涉及到一部分迭代器的知识.但是觉得还是不够过瘾,很多需要说清楚 ...

  2. 轻量级“集合”迭代器-Generator

    Generator是PHP 5.5加入的新语言特性.但是,它似乎并没有被很多PHP开发者广泛采用.因此,在我们了解PHP 7对Generator的改进之前,我们先通过一个简单却显而易见的例子来了解下G ...

  3. C#设计模式-迭代器模式

    一. 迭代器(Iterator)模式 迭代器是针对集合对象而生的,对于集合对象而言,必然涉及到集合元素的添加删除操作,同时也肯定支持遍历集合元素的操作,我们此时可以把遍历操作也放在集合对象中,但这样的 ...

  4. 设计模式(十):从电影院中认识"迭代器模式"(Iterator Pattern)

    上篇博客我们从醋溜土豆丝与清炒苦瓜中认识了“模板方法模式”,那么在今天这篇博客中我们要从电影院中来认识"迭代器模式"(Iterator Pattern).“迭代器模式”顾名思义就是 ...

  5. Python(四)装饰器、迭代器&生成器、re正则表达式、字符串格式化

    本章内容: 装饰器 迭代器 & 生成器 re 正则表达式 字符串格式化 装饰器 装饰器是一个很著名的设计模式,经常被用于有切面需求的场景,较为经典的有插入日志.性能测试.事务处理等.装饰器是解 ...

  6. 用struts2标签如何从数据库获取数据并在查询页面显示。最近做一个小项目,需要用到struts2标签从数据库查询数据,并且用迭代器iterator标签在查询页面显示,可是一开始,怎么也获取不到数据,想了许久,最后发现,是自己少定义了一个变量,也就是var变量。

    最近做一个小项目,需要用到struts2标签从数据库查询数据,并且用迭代器iterator标签在查询页面显示,可是一开始,怎么也获取不到数据,想了许久,最后发现,是自己少定义了一个变量,也就是var变 ...

  7. Java迭代器

    迭代器在其实就是指针,读取集合或者数组中的一个值,读完以后又指向下一条数据. iterator() 迭代器只读,不能改效率要比for循环高 迭代器的一些方法: HasNext() 如果仍有元素可以迭代 ...

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

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

  9. 设计模式02迭代器(java)

    先贴代码,有空来写内容. 1.定义集合 import java.util.List; import java.util.ArrayList; //coollection是我自己定义的一个集合,因为要写 ...

  10. JAVA编程思想(第四版)学习笔记----11.5 List,11.6迭代器

    Collection类的层次结构图(来源与网络)如下所示: 接口:Iterator<T> public interface Iterable<T> Iterable<T& ...

随机推荐

  1. 小程序开发-媒体组件image

    image 图片组件,支持 JPG.PNG.SVG.WEBP.GIF 等格式,2.3.0 起支持云文件ID. 所有属性如下: Tips image组件默认宽度320px.高度240px image组件 ...

  2. 20191002思维导图工具MindManager 000 033

  3. CentOS 7 安装部署 cassandra作为kairosdb的数据存储

    环境 Centos 7.4 java 1.8.0 安装步骤 java yum -y install java-1.8.0-openjdk* cassandra wget https://mirrors ...

  4. Ubuntu修改默认Python版本,你了解多少~

    目录 1 查看Python版本 1.1 查看装有哪些版本 1.2 查看默认版本 2 修改Python默认版本 2.1 基于文件修改 2.2 基于软链接修改 1 查看Python版本 1.1 查看装有哪 ...

  5. (python)生产者消费者模型

    生产者消费者模型当中有两大类重要的角色,一个是生产者(负责造数据的任务),另一个是消费者(接收造出来的数据进行进一步的操作). 为什么要使用生产者消费者模型? 在并发编程中,如果生产者处理速度很快,而 ...

  6. flask提交表单验证不通过,以及CSRF攻击原理

    学习表单的问题1. 提交表单时怎么都无法验证通过 记录一下,自己的学习bug,主要是因为在模板中书写渲染的语句时,把CSRF的字段名写错了. 因为在模板中书写一些语句是没有提示的,自己手动敲代码容易出 ...

  7. 《C++深度解析》课程目录

    <C++深度解析>课程目录 第1课 - 学习 C++ 的意义 第2课 - C到C++的升级     第3课 - 进化后的const分析 第4课 - 布尔类型和引用 第5课 - 引用的本质分 ...

  8. gcc之__attribute__简介及对齐参数介绍

    GNU C的一大特色就是__attribute__机制.__attribute__机制可以设置函数属性(Function Attribute).变量属性(Variable Attribute)和类型属 ...

  9. 数据库:浅谈DML、DDL、DCL的区别

    简介 SQL是一个标准的数据库语言,是面向集合的描述性非过程化语言.它功能强,效率高,简单易学易维护(迄今为止,我还没见过比它还好学的语言).然而SQL语言由于以上优点,同时也出现了这样一个问题:它是 ...

  10. 我的Python自学之路-003 字符串的知识

    '''字符串是以引号或者单引号括起来的任意文本,例如"123","asdfjk",'adfa'引号或者单引号,只是一种表示方法,并不是字符串的一部分如果字符串本 ...