C# 图解教程 第5版 —— 第19章 枚举器和迭代器

文章目录

    • 19.1 枚举器和可枚举类型
    • 19.2 IEnumerator 接口
    • 19.3 IEnumerable 接口
    • 19.4 泛型枚举接口
    • 19.5 迭代器
      • 19.5.1 迭代器块
      • 19.5.2 使用迭代器来创建枚举器
      • 19.5.3 使用迭代器来创建可枚举类型
    • 19.6 常见迭代器模式
    • 19.7 产生多个可枚举类型
    • 19.8 将迭代器作为属性
    • 19.9 迭代器的实质

19.1 枚举器和可枚举类型

使用 foreach 语句

​ 下面是使用 foreach 语句遍历数组的示例。

image-20231218145254811 image-20231218145309824

​ 数组可以使用这种方式访问的原因是:数组提供了枚举器对象。枚举器知道数组中元素的次序,并依次返回数组中的元素。

​ 对于有枚举器的类型而言,我们使用 GetEnumerator 方法来获取其拥有的枚举器,实现该方法的类型称为可枚举类型。数组就是可枚举类型。

image-20231218145604337
图19.1 枚举器和可枚举类型概览

​ foreach 结构设计用来和可枚举类型一起使用,如下行为会被执行:

  1. 调用 GetEnumerator 方法获取对象的枚举器。
  2. 从枚举起中请求每一项并作为迭代变量(可读不可写)。
image-20231218145810666

19.2 IEnumerator 接口

​ 实现了 IEnumerator 接口的枚举器包含 3 个函数成员:

  1. Current:返回序列中当前位置项的属性。
    • 为只读属性。
    • 返回 object 类型的引用。
  2. MoveNext:是将枚举器位置前进到集合中下一项的方法,返回布尔值。
    • 如果新的位置有效,返回 true。
    • 如果新的位置无效,返回 false。
  3. Reset:将位置重置为原始状态。
    • 枚举器的原始位置在序列中的第一项之前,因此 MoveNext 必须在第一次使用 Current 之前调用。
image-20231218150209771
图19.2 小集合的枚举器

​ 在编写 foreach 循环的时候,C# 编译器将生成与下面十分类似的代码(以 CIL 的形式)。

image-20231218150415769 image-20231218150445568
图19.3 .NET 数组类实现了 IEnumerator

19.3 IEnumerable 接口

​ 可枚举类是指实现了 IEnumerable 接口的类,该接口只有一个成员——GetEnumerator,返回对象的枚举器。

image-20231218150743647
图19.4 GetEnumerator 方法返回类的一个枚举器对象
image-20231218150941982

使用 IEnumerable 和 IEnumerator 的示例

image-20231218151148423 image-20231218151203527

19.4 泛型枚举接口

​ 使用 C# 泛型和非泛型的方式相差不大。

  • 对于非泛型接口形式:
    • IEnumerable 接口的 GetEnumerator 方法返回实现 IEnumerator 的枚举器类实例。
    • 实现 IEnumerator 的类实现了 Current 属性,返回 object 类型的引用,然后将其转化为对象的实际类型。
  • 对于泛型接口形式:
    • IEnumerable<T> 接口的 GetEnumerator 方法返回实现 IEnumerator<T> 的枚举器类实例。
    • 实现 IEnumerator<T> 的类实现了 Current 属性,返回实际类型的实例,而不是 object 基类的引用。
    • 实际上泛型接口的声明是协变的,即 IEnumerable<out T> 和 IEnumerator<out T>,因此这些接口的对象可以是派生的类型。

​ 泛型版本简单易用,但其结构略显复杂。

image-20231218151811109
图19.5 实现 IEnumerable<T> 接口的类的结构

19.5 迭代器

​ 可枚举类和枚举器在 .NET 集合类中被广泛使用,从 C# 2.0 版本开始提供了创建枚举器和可枚举类型更简单的方式,将这种结构称为迭代器

​ 在下面这个示例中:

  • 迭代器返回一个泛型枚举器,该枚举器返回 3 个 string 类型的项。
  • yield return 语句声明这是枚举中的下一项。
image-20231218152306099

​ 下面的方法声明了另一个版本,输出结果与上面相同。

image-20231218152341904

​ 枚举器不会一次返回所有的元素,而是每次访问 Current 属性时返回一个新值。

19.5.1 迭代器块

​ 迭代器块是有一个或多个 yield 语句的代码块,可以是如下任意一种代码块:

  • 方法主体。
  • 访问器主体。
  • 运算符主体。

​ 迭代器块描述了希望编译器为我们创建的枚举器类的行为,其中的代码描述了如何枚举元素。

  1. yield return:指定序列中要返回的下一项。
  2. yield break:指定在序列中没有其他项。

​ 编译器得到有关枚举项的描述后,会构建包含所有需要的方法(MoveNext)和属性(Current)实现的枚举器类,产生的类被嵌套包含在声明迭代器的类中。

image-20231218152851321
图19.6 根据指定的返回类型,可以让迭代器产生枚举器或可枚举类型

19.5.2 使用迭代器来创建枚举器

image-20231218153055412 image-20231218153138376
  • 图中左边演示了返回类型是 IEnumerator<string>。
  • 图中右边演示了它有一个嵌套类实现了 IEnumerator<string>。
image-20231218153301556
图19.7 迭代器块产生了枚举器

19.5.3 使用迭代器来创建可枚举类型

​ 本节例子使用迭代器来创建可枚举类型,而不是枚举器。

  • BlackAndWhite 迭代器方法返回 IEnumerable<string> 而不是 IEnumerator<string>。
  • MyClass 首先调用 BlackAndWhite 方法获取可枚举类型对象,然后调用该对象的 GetEnumerator 方法来获取结果,从而实现 GetEnumerator 方法。
image-20231218154115386
  • 图中左边演示了返回类型是 IEnumerable<string>。
  • 图中右边演示了它有一个嵌套类实现了 IEnumerator<string> 和 IEnumerable<string>。
image-20231218154355077
图19.8 编译器生成的类是可枚举类型并返回一个枚举器。编译器还生成了方法 BlackAndWhite,返回可枚举对象

19.6 常见迭代器模式

  1. 实现返回枚举器的迭代器。

    通过实现 GetEnumerator 方法让类可枚举,它返回由迭代器返回的枚举器。

  2. 实现返回可枚举类型的迭代器。

    实现 GetEnumerator 来让类本身可枚举;或不实现,来让类不可枚举。

image-20231218155301997
图19.9 常见的迭代器模式

19.7 产生多个可枚举类型

​ Spectrum 类有两个可枚举类型的迭代器,但类本身不可枚举,因为没有实现 GetEnumerator 方法。

image-20231218155441822 image-20231218155514934

19.8 将迭代器作为属性

​ 本示例演示两个方面的内容:

  1. 使用迭代器产生两个枚举器的类。
  2. 演示迭代器如何实现为属性,而不是方法。

​ 这段代码声明了两个属性来定义两个不同的枚举器。GetEnumerator 方法根据 _listFromUVtoIR 布尔变量的值返回两个枚举器中的一个。如果 _listFromUVtoIR 为 true,则返回 UVtoIR 枚举器;否则,返回 IRtoUV 枚举器。

image-20231218160024023 image-20231218160102546 image-20231218160121319

19.9 迭代器的实质

​ 有关迭代器的其他重要事项:

  • 迭代器需要 System.Collections.Generic 命名空间,因此需要使用 using 指令进行引入。
  • 在编译器生成的枚举器中,不支持 Reset 方法。Reset 是接口需要的方法,所以实现了它,但调用时总是抛出 System.NotSupportedException 异常。

​ 在后台,编译器生成的枚举器类总是包含 4 个状态的状态机。

  1. Before:首次调用 MoveNext 的初始状态。
  2. Running:调用 MoveNext 后进入这个状态。
    • 枚举器检测并设置下一项的位置。
    • 遇到 yield return、 yield break 或在迭代器中结束时,退出 Running 状态。
  3. Suspended:状态机等待下次调用 MoveNext 的状态。
  4. After:没有更多项可以枚举的状态。
image-20231218161138144
图19.10 迭代器状态机

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

计算机毕业设计—基于Koa+vue的高校宿舍管理系统宿舍可视化系统

项目介绍 项目背景 随着科技的发展&#xff0c;智能化管理越来越重要。大学生在宿舍的时间超过了1/3&#xff0c;因此良好的宿舍管理对学生的生活和学习极为关键。学生宿舍管理系统能够合理安排新生分配宿舍&#xff0c;不浪费公共资源&#xff0c;减轻学校管理压力&#xff…

IDEA运行JSP启动后页面中文乱码

源代码截图&#xff1a; 运行结果截图&#xff1a; 在<head>标签内加入代码 <% page contentType"text/html; charsetgb2312"%> 重启服务器&#xff0c;问题已改善 ————————————————— 该文仅供学习以及参考&#xff0c;可做笔记收藏…

【工具使用-Qt】Qt如何查看帮助文档

一&#xff0c;简介 Qt不需要单独下载帮助文档&#xff0c;在安装的时候&#xff0c;就已经帮你下载好了&#xff0c;在目录&#xff1a;安装目录/Qt5.14.2/Docs/目录下了。 二&#xff0c;查看方法 打开IDE&#xff0c;点击“帮助”&#xff1a; 输入想要查找的内容&…

pytorch文本分类(三)模型框架(DNNtextCNN)

pytorch文本分类&#xff08;三&#xff09;模型框架&#xff08;DNN&textCNN&#xff09; 原任务链接 目录 pytorch文本分类&#xff08;三&#xff09;模型框架&#xff08;DNN&textCNN&#xff09;1. 背景知识深度学习 2. DNN2.1 从感知器到神经网络2.2 DNN的基本…

电脑操作系统深度剖析:Windows、macOS和Linux的独特特性及应用场景

导言 电脑操作系统是计算机硬件和应用软件之间的桥梁&#xff0c;不同的操作系统在用户体验、性能和安全性方面有着独特的特色。电脑操作系统是计算机系统中的核心组件&#xff0c;不同的操作系统在设计理念、用户体验和应用领域上存在显著差异。本文将深入探讨几种常见的电脑操…

智能优化算法应用:基于黑猩猩算法3D无线传感器网络(WSN)覆盖优化 - 附代码

智能优化算法应用&#xff1a;基于黑猩猩算法3D无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用&#xff1a;基于黑猩猩算法3D无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.黑猩猩算法4.实验参数设定5.算法结果6.参考文…

Excel小技能:excel如何将数字20231211转化成指定日期格式2023/12/11

给了一串数字20231211&#xff0c;想要转成指定格式的日期格式&#xff0c;发现设置单元格格式为指定日期格式不生效&#xff0c;反而变成很长很长的一串#这个&#xff0c;如图所示&#xff1a; 其实&#xff0c;正确的做法如下&#xff1a; 1&#xff09;打开数据功能界面&am…

Android-高效加载大图

Android 高效加载大图 前言读取位图尺寸和类型将按比例缩小的版本加载到内存中 前言 图片有各种形状和大小。在很多情况下&#xff0c;它们的大小超过了典型应用界面的要求。例如&#xff0c;系统“图库”应用会显示使用 Android 设备的相机拍摄的照片&#xff0c;这些照片的分…

助力智能人群检测计数,基于YOLOv8开发构建通用场景下人群检测计数识别系统

在一些人流量比较大的场合&#xff0c;或者是一些特殊时刻、时段、节假日等特殊时期下&#xff0c;密切关注当前系统所承载的人流量是十分必要的&#xff0c;对于超出系统负荷容量的情况做到及时预警对于管理团队来说是保障人员安全的重要手段&#xff0c;本文的主要目的是想要…

智能手表上的音频(五):录音

上篇讲了语音通话&#xff0c;本篇讲录音。录音功能就是把录到的音频保存成文件。保存文件的格式支持两种&#xff1a;一是PCM(16K采样)的WAV格式&#xff0c;二是AMR-NB&#xff08;8k采样&#xff09;的AMR格式。WAV格式简单&#xff1a;44字节的文件头PCM 数据&#xff0c;示…

关于前端学习的思考-浮动元素嵌套块级元素12.18

1、块级元素嵌套浮动元素 先摆图片&#xff0c;当橘色的盒子高度减少的时候&#xff0c;NK AD TB PK NN并不会减少。如何解决呢&#xff1f; 加一个overflow&#xff1a;clip或者hidden 2、浮动元素嵌套块级元素 加一个overflow&#xff1a;clip或者hidden 综上所述&#xff0…

DC-5靶场

目录 DC-5靶机&#xff1a; 先进行主机发现&#xff1a; 发现文件包含&#xff1a; 上传一句话木马&#xff1a; 反弹shell&#xff1a; 提权漏洞利用&#xff1a; 下载exp&#xff1a; 第一个文件 libhax.c 第二个文件r…

人工智能_机器学习069_SVM支持向量机_网格搜索_交叉验证参数优化_GridSearchCV_找到最优的参数---人工智能工作笔记0109

然后我们再来说一下SVC支持向量机的参数优化,可以看到 这次我们需要,test_data这个是测试数据,容纳后 train_data这个是训练数据 这里首先我们,导出 import numpy as np 导入数学计算包 from sklearn.svm import SVC 导入支持向量机包 分类器包 def read_data(path): wit…

apache shiro 反序列化漏洞解决方案

apache shiro 反序列化漏洞解决方案 反序列化漏洞解决方案产生原因解决方案1&#xff1a;1.升级shiro至最新版本1.7.1解决方案2&#xff1a;修改rememberMe默认密钥&#xff0c;生成随机密钥。 反序列化漏洞解决方案 反序列化漏洞介绍 序列化&#xff1a;把对象转换为字符串或…

弹幕情感分析可视化

弹幕情感分析可视化 引言1. 弹幕数据爬取2. 弹幕数据处理3. 弹幕数据可视化4. 弹幕情感分析5. 创新点&#xff1a;弹幕情感倾向分布 引言 当今互联网时代&#xff0c;大量的弹幕数据蕴含着丰富的信息&#xff0c;通过对这些数据进行分析和可视化&#xff0c;我们能够深入了解用…

promise到底是个什么??

promise是什么&#xff1f; promise是一门新的技术&#xff08;es6规范&#xff09; promise是js中进行异步编程的新的解决方案 旧的方案是单纯的使用回调函数 具体的说 promise是构造函数 可以快速构建promise对象 快速获取成功或者失败的值 异步操作有哪些&#xff1…

HackTheBox-Machines--Analytics

文章目录 1 端口扫描2 测试思路3 漏洞探测4 权限获取5 权限提升 Analytics 测试过程 1 端口扫描 nmap -sC -sV 10.129.205.1422 测试思路 目标服务器只开启了80端口&#xff0c;所以出发点从80端口开始。对于web页面&#xff0c;能做的大致思路有&#xff1a; 1.目录扫描   2…

【K8S基础】-k8s的核心概念pod

一、Pod 是什么 1.1 Pod 的定义和概念 在Kubernetes中&#xff0c;Pod是创建或部署的最小/最简单的基本单位。一个Pod代表着集群上正在运行的一个进程&#xff0c;它封装了一个或多个应用容器&#xff0c;并且提供了一些共享资源&#xff0c;如网络和存储&#xff0c;每个Pod…

Java编程与电脑生产力的奇妙故事

标题 《Java编程与电脑生产力的奇妙故事》摘要引言电脑选购的艰难决策决定拿下电脑的那一刻1. 用途和需求2. 硬件规格3. 便携性和设计4. 品牌和可靠性5. 预算 电脑与Java编程的默契数码工具与工作成果的交流1. 开发环境选择2. 代码编辑和调试3. 应用程序部署和运行4. 版本控制和…

Acrel-1000DP分布式光伏系统在某重工企业18MW分布式光伏中应用——安科瑞 顾烊宇

摘 要&#xff1a;分布式光伏发电特指在用户场地附近建设&#xff0c;运行方式以用户侧自发自用、余电上网&#xff0c;且在配电系统平衡调节为特征的光伏发电设施&#xff0c;是一种新型的、具有广阔发展前景的发电和能源综合利用方式&#xff0c;它倡导就近发电&#xff0c;就…