深入解析 迭代器

前言

问:什么是迭代器 ?  

答:在C# 中,迭代器是一种设计模式,它允许一个类或集合(比如数组、列表或字典)的实例提供一种遍历其元素的方式。在C#2时引入的迭代器,来简化这一过程。


        在C#中有少数接口是有特定的语言来支持,如IDisposable 接口就由Using语句来获得支持,其中IEnumerable就由foreach来支持。本文就围绕着当前两个接口来介绍我们的示例。

迭代器的介绍

        迭代器是包含迭代器块,通常是方法或者是属性。迭代器通常返回类型都是IEnumerable或IEnumerable<T>类型的方法或属性,每个迭代器都有一个生成类型,返回类型是非泛型时则为Object类型,是泛型时则是返回泛型的类型实例类型。如IEnumerable<int>则返回的类型就是int。yield return 在迭代器中代表返回某一个值 如 yield return 1就是返回1这个数值。 yield break 则代表终止迭代器的进行。

迭代器的执行逻辑

        通常迭代器是在foreach语句当中调用的,在foreach语句当中我们对一个非泛型集合进行迭代。执行顺序:

1:调用返回类型为GetEnumerator类型的方法

2:返回一个IEnumerator的引用,调用IEnumerator接口中的方法MoveNext()

3:通过当前方法的返回值来判断是否有值 如果有值(返回 True)则获取当前接口中的属性Current将其返回。

4:在返回True的情况下继续调用MoveNext方法循环,直到当前方法返回false代表当前已经不存在值的情况下结束当前迭代。

创建一个迭代器

        创建自定义的迭代器通常涉及定义一个返回IEnumerator<T>IEnumerator接口的方法,并在其中实现遍历集合的逻辑。

举个例子(目标框架不是framework 是.Net 8):

foreach (int i in new MyCollection())
{Console.WriteLine(i);
}
public class MyCollection
{private int[] items = { 1, 2, 3, 4, 5 };public IEnumerator<int> GetEnumerator(){foreach (var item in items){yield return item; // 使用 yield return 返回每个元素  }}
}

示例解释:   当前通过yield return来返回迭代中的值,迭代当前类输出结果为 1 2 3 4 5 

 模拟实现迭代器的执行逻辑

举个例子:

new MyCollection();
public class MyCollection
{private int[] items = { 1, 2, 3, 4, 5 };public IEnumerable<int> GetEnumerator(){foreach (var item in items){yield return item; // 使用 yield return 返回每个元素  }}public MyCollection(){IEnumerable<int> IEnumerators = GetEnumerator();using (IEnumerator<int> enmerator = IEnumerators.GetEnumerator()){while (enmerator.MoveNext()) {int item = enmerator.Current;Console.WriteLine(item);}}}
}

示例解释:与上述迭代器的执行逻辑描述的执行顺序是一样的。

迭代器是延迟执行

        为什么说迭代器是延时执行?

        因为当迭代器第一次调用MoveNext()方法,实际上返回时当前这个方法仿佛被暂停了,生成的代码会追踪当前语句执行进度。如我们在循环当中返回一些变量,每当我们返回一次那么我们当前的这个方法就会被暂停直到下一次调用MoveNext它就会在上次暂停的地方继续执行。

        简单来说,迭代器在执行时采用延时执行的方式。当迭代器第一次调用MoveNext()方法时,它会执行到yield return语句,并返回当前的值。在这个过程中,迭代器的状态被暂停,并记录下当前执行的位置。下次调用MoveNext()方法时,迭代器会从上次暂停的位置继续执行,返回下一个值。

        这种延时执行的机制使得迭代器可以高效地处理大量数据或者耗时的操作。它不需要一次性生成所有的结果,而是按需逐个生成结果,减少了内存占用和计算开销。

所以可以说迭代器是一种延时执行的机制,它能够提供有效的迭代操作和节省资源的优势。

利用延迟执行这一特性来验证一下

举个例子(目标框架不是framework 是.Net 8):

foreach (var i in new S().GetEnumerator())
{Console.WriteLine(i);
}
public class S
{public IEnumerable<int> GetEnumerator(){try{yield return 1;yield return 2;yield return 3;yield return 4;}finally{Console.WriteLine("5");}}}

示例解释:

        当前代码块就是输出结果顺序就是 1 2 3 4 5 很明显就是前面我们提到的记录当前位置后继续执行 也就是说并没有重新运行。 


问:如果我们提前跳出会不会就不会执行 finally了而直接结束当前迭代了?

答:不会,会在结束之前调用finally代码块。

举个例子(修改上述部分代码)

 public IEnumerable<int> GetEnumerator(){try{yield return 1;yield break;}finally{Console.WriteLine("5");}}

输出结果:1 5 


问:为什么说finally因为在迭代器中结合?

答:使用finally代码块可以执行在结束迭代后的释放工作(如IO流的操作)

补充:

1 如果大家想了解MoveNext方法的实现逻辑可以网上查询这里不做介绍。

2 如有解释错误欢迎大家指出,谢谢大家😊

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/593767.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【每天五道题,轻松公务员】Day2:世界地理

目录 专栏了解 ☞欢迎订阅☜ ★专栏亮点★ ◇专栏作者◇ 世界地理 题目一 题目二 题目三 题目四 题目五 答案 详细讲解 专栏了解 ☞欢迎订阅☜ 欢迎订阅此专栏&#xff1a;考公务员&#xff0c;必订&#xff01;https://blog.csdn.net/m0_73787047/category_1254…

顶帽运算在OpenCv中的应用

项目背景 假如我们拍了一张自拍&#xff0c;想为自己的照片添加一个酷炫的火星飞舞的效果&#xff0c;素材库中正好有一张火焰的照片&#xff0c;如果想去除图中的火焰&#xff0c;只保留火星效果&#xff0c;可以使用顶帽子算法 图片中的火星部分正好属于比周围亮一些的斑块…

LabVIEW开发滚筒洗衣机动态监测系统

LabVIEW软件在滚筒洗衣机的动态监测和分析中扮演着关键角色。本案例展示了如何利用LabVIEW开发的系统来优化洗衣机的性能和可靠性。 首先&#xff0c;在建立洗衣机的动力学模型基础上&#xff0c;利用LabVIEW进行了关键零部件的动态优化设计。通过LabVIEW的高级计算和模拟功能…

【JavaFX】JDK11 基于Gson、hutool、Jackson持久化存储实体类数据的解决方案 (读取、追加、去重、写入json对象)

文章目录 开发环境效果前言一、Gson是什么?二、使用步骤1.引入依赖2.创建实体类创建 JsonFileService类创建JsonFileService的实现类 JsonFileServiceImpl三、实现效果开发环境 JDK11IDEA 2023.3Gson、hutool、JacksonJavaFX 11效果 前言 使用JDK1

112. 雷达设备(贪心/逆向思考)

题目&#xff1a; 112. 雷达设备 - AcWing题库 输入样例&#xff1a; 3 2 1 2 -3 1 2 1输出样例&#xff1a; 2 思路&#xff1a; 代码&#xff1a; #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #include<…

组件通信方式

组件通信方式有&#xff1a;vuex&#xff0c;ref&#xff0c;父子通信&#xff08;父传子、子传父&#xff09;&#xff0c;兄弟通信(eventBus)&#xff0c; 祖先后代通信&#xff08;依赖注入&#xff09; 父传子&#xff1a;父组件内&#xff1a;在子组件标签上设置自定义属…

BMS、AFE、菊花链技术

一、BMS的分布式架构和集中式架构 AFE在从板中&#xff0c;用来采集电池电压和温度&#xff0c;以及均衡管理 BMS通常以分布式架构为主&#xff0c;即分为主板和从板。原来主从板上都有微处控制器。从板采集单体电池电压和温度&#xff0c;通过CAN总线传给主板。 而现在的趋势…

Oracle-数据库迁移之后性能变慢问题分析

问题背景&#xff1a; ​一套Oracle11.2.0.4的RAC集群&#xff0c;通过Dataguard switchover方式迁移到新机器之后&#xff0c;运行第一天应用报障说应用性能慢&#xff0c;需要进行性能问题排查 问题分析&#xff1a; 首先&#xff0c;登陆到服务器&#xff0c;用TOP看一眼两个…

虾皮马来站点选品:在虾皮(Shopee)5个热门品类和市场特点

在虾皮&#xff08;Shopee&#xff09;马来西亚站点选择商品时&#xff0c;卖家应该考虑一些热门品类和市场特点&#xff0c;以确保他们的产品能够满足当地消费者的需求并取得良好的销售业绩。以下是在虾皮&#xff08;Shopee&#xff09;马来西亚站点销售商品时需要考虑的五个…

高德地图信息窗体设置

1. 添加默认信息窗体 //构建信息窗体中显示的内容var info [];info.push(<div style"height: 36px; line-height: 45px; padding: 0px 20px; white-space:nowrap;">位置&#xff1a;北京</div>);info.push(<div style"height: 36px; line-heig…

裂变新模式:分销市场的翘楚

在当今的商业世界&#xff0c;推荐机制已经成为一种重要的营销策略。通过用户推荐&#xff0c;企业不仅能够扩大品牌影响力&#xff0c;还能有效降低获客成本。然而&#xff0c;如何设计一个合理的推荐机制&#xff0c;使得用户有足够的动力去推荐新人&#xff0c;同时保持团队…

【Java】接口和抽象类有什么共同点和区别?

个人简介&#xff1a;Java领域新星创作者&#xff1b;阿里云技术博主、星级博主、专家博主&#xff1b;正在Java学习的路上摸爬滚打&#xff0c;记录学习的过程~ 个人主页&#xff1a;.29.的博客 学习社区&#xff1a;进去逛一逛~ 【Java】接口和抽象类有什么共同点和区别&…

基于遗传算法的药品配送,遗传算法原理

目录 背影 遗传算法的原理及步骤 基本定义 编码方式 适应度函数 运算过程 代码 结果分析 完整代码下载: 基于遗传算法的药品配送 背影 基于遗传算法的药品配送,求解运算量大,一般都无法用直接求解,本文用遗传算法进行求解,遗传算法拥有更好的全局寻优能力, 遗传算法 …

SQL Server注入之攻防技战法

那天下着很大的雨&#xff0c;母亲从城里走回来的时候&#xff0c;浑身就是一个泥人&#xff0c;那一刻我就知道我没有别的选择了 1.Mssql报错注入 0.判断数据库类型 1.爆当前用户名 2.爆版本 3.爆服务器名 4.判断数据库个数 5.获取全部数据库 语句只适合>2005 爆当前数据…

DDD落地实践-架构师眼中的餐厅(转)

本文以餐厅场景为叙事主线&#xff0c;以领域驱动为核心思想&#xff0c;结合架构设计与功能设计方法论。是从领域分析到落地的全过程案例&#xff0c;内容偏重于落地&#xff0c;因此不乏一些探讨&#xff0c;欢迎指正。 文章较长、全程干货、耐心读完、必有收获。 本文不针…

算法训练第五十七天|647. 回文子串、516.最长回文子序列

647. 回文子串&#xff1a; 题目链接 给你一个字符串 s &#xff0c;请你统计并返回这个字符串中 回文子串 的数目。 回文字符串 是正着读和倒过来读一样的字符串。 子字符串 是字符串中的由连续字符组成的一个序列。 具有不同开始位置或结束位置的子串&#xff0c;即使是由…

【docker】如何编写dockerfile文件,构建docker镜像

如何编写dockerfile文件&#xff0c;构建docker镜像 一、docker 镜像与 dockerfile1.1 什么是Docker镜像1.2 Docker 镜像的结构 二、dockerfile 中常用的构建指令三、dockerfile 内容示例四、构建 docker 镜像 一、docker 镜像与 dockerfile 1.1 什么是Docker镜像 Docker镜像…

虾皮跨境电商物流:为卖家提供高效灵活的物流解决方案

虾皮&#xff08;Shopee&#xff09;作为一家知名的跨境电商平台&#xff0c;其物流服务是其成功的关键因素之一。虾皮跨境电商物流服务为卖家提供了一站式的物流解决方案&#xff0c;从订单处理到最终交付&#xff0c;为卖家提供高效、灵活、成本效益高的物流服务&#xff0c;…

【教学类-43-13】 20240103 (4宫格数独:错误版:768套) 不重复的基础模板数量:768套

作品展示&#xff1a;——4宫格 768套不重复模板&#xff08;64页*12套题&#xff09; 有错误&#xff0c;实际数量小于768套 背景需求&#xff1a; 测试4宫格数独基础模板有几种。 写个程序&#xff0c;验算是不是真的是乘阶法的288种。 代码展示&#xff1a; 768套4宫格题…

Python for与while循环的介绍和对应练习题的巩固

for循环 重复执行同一段代码就是循环 循环列表 for val in list_name: list_num [1,2,3,4,5,6,7,8,9] for i in list_num:print(i)代码执行顺序 从上往下依次执行 遍历 通过某种顺序把某种集合所有元素都访问一遍 list_food{"火锅","烧烤","张…