.NET中的迭代器(Iterator)
更新记录
本文迁移自Panda666原博客,原发布时间:2021年6月30日。
一、迭代器介绍
C#2.0开始,我们可以使用迭代器(iterator)。编译器自动把我们定义的迭代器生成 可枚举类型 或 枚举器。迭代器需要System.Collections.Generic命名空间,要使用using引用它。
using System.Collections.Generic;
二、声明迭代器
迭代器看起来非常像一个方法,但实际上是有本质区别的。编译器将迭代器转换为私有类,然后在类中实现IEnumerable 或者 IEnumerator的方法,即会将其转为可迭代类型。迭代器可以包含在:方法、属性、索引器中。所以迭代器的返回类型只可能是以下四种类型:
System.Collection.IEnumerable
System.Collection.Generic.IEnumerable<T>
System.Collection.IEnumerator
System.Collection.Generic.IEnumerator<T>
在迭代器中通过yield return语句声明枚举中的下一项,枚举器不会一次返回所有元素,每次访问Current属性返回一个新值,iterator可以在method, property, indexer内实现。
实例:返回可枚举类型的迭代器
public class PandaTestClass
{
public IEnumerable<string> GetEnumerator()
{
yield return "Panda";
yield return "Cat";
yield return "Dog";
yield return "Monkey";
yield return "Donkey";
}
}
实例:返回枚举器的迭代器
public class PandaTestClass:IEnumerable<string>
{
public IEnumerator<string> GetEnumerator()
{
yield return "Panda";
yield return "Cat";
yield return "Dog";
yield return "Monkey";
yield return "Donkey";
}
IEnumerator IEnumerable.GetEnumerator()
{
throw new NotImplementedException();
}
}
实例:可正序取数也可反向取数的迭代器
public class PandaTestClass
{
private string[] animals { get; set; }
public PandaTestClass()
{
this.animals = new string[]
{
"Panda",
"Cat",
"Dog",
"Monkey",
"Donkey"
};
}
/// <summary>
/// 正序访问
/// </summary>
/// <returns></returns>
public IEnumerable<string> GetAnimal()
{
foreach (var item in this.animals)
{
yield return item;
}
}
/// <summary>
/// 反序访问
/// </summary>
/// <returns></returns>
public IEnumerable<string> GetAnimalReverse()
{
var animalsReversed = this.animals.Reverse();
foreach (var item in animalsReversed)
{
yield return item;
}
}
}
实例:在属性中定义迭代器
class PandaTestClass
{
public IEnumerable<int> SomeProp
{
get
{
yield return 666;
yield return 888;
yield return 999;
}
}
public IEnumerator<int> SomeProp2
{
get
{
yield return 666;
yield return 888;
yield return 999;
}
}
}
三、迭代器的内部状态
迭代器在编译器生成的枚举器中,没有实现Reset方法,所以不可以调用Reset。在后台编译器把迭代器转换为的枚举器类包含4个状态:
Before 首次调用MoveNext之前的状态
Running 调用MoveNext后进入这个状态
Supended 状态机等待下次调用MoveNext的状态
After 没有更多项可枚举

四、迭代器与异常处理
yield return语句不可以出现在try/catch/finally语句块中。原因是:迭代器在编译阶段会转为私有类型放在这些语句块中会导致异常复杂。但是可以放在try/finally语句块中。
实例:迭代器的异常处理
IEnumerable<string> Foo()
{
try { yield return "One"; } // OK
finally { ... }
}
.NET中的迭代器(Iterator)的更多相关文章
- ES6中的迭代器(Iterator)和生成器(Generator)
前面的话 用循环语句迭代数据时,必须要初始化一个变量来记录每一次迭代在数据集合中的位置,而在许多编程语言中,已经开始通过程序化的方式用迭代器对象返回迭代过程中集合的每一个元素 迭代器的使用可以极大地简 ...
- 牛客网Java刷题知识点之Java 集合框架的构成、集合框架中的迭代器Iterator、集合框架中的集合接口Collection(List和Set)、集合框架中的Map集合
不多说,直接上干货! 集合框架中包含了大量集合接口.这些接口的实现类和操作它们的算法. 集合容器因为内部的数据结构不同,有多种具体容器. 不断的向上抽取,就形成了集合框架. Map是一次添加一对元素. ...
- ES6中的迭代器(Iterator)和生成器(Generator)(一)
用循环语句迭代数据时,必须要初始化一个变量来记录每一次迭代在数据集合中的位置,而在许多编程语言中,已经开始通过程序化的方式用迭代器对象返回迭代过程中集合的每一个元素 迭代器的使用可以极大地简化数据操作 ...
- c++中的迭代器 iterator
迭代器iterator的作用类似于指针. iterator只有针对制定<类型>的容器才有效.例如: vector<int> vec; vector<int>::it ...
- ES6中的迭代器(Iterator)和生成器(Generator)(二)
一.内建迭代器 迭代器是ES6的一个重要组成部分,在ES6中,已经默认为许多内建类型提供了内建迭代器,只有当这些内建迭代器无法实现目标时才需要自己创建.通常来说当定义自己的对象和类时才会遇到这种情况, ...
- Python中生成器generator和迭代器Iterator的使用方法
一.生成器 1. 生成器的定义 把所需要值得计算方法储存起来,不会先直接生成数值,而是等到什么时候使用什么时候生成,每次生成一个,减少计算机占用内存空间 2. 生成器的创建方式 第一种只要把一个列表生 ...
- 如何正确遍历删除List中的元素(普通for循环、增强for循环、迭代器iterator、removeIf+方法引用)
遍历删除List中符合条件的元素主要有以下几种方法: 普通for循环 增强for循环 foreach 迭代器iterator removeIf 和 方法引用 其中使用普通for循环容易造成遗漏元素的问 ...
- Python中的可迭代Iterable和迭代器Iterator
目录 Iterable可迭代对象 如何判断对象是否是可迭代对象Iterable Iterator迭代器 如何判断对象是否迭代器Iterator 将Iterable转换成Iterator Iterabl ...
- 用struts2标签如何从数据库获取数据并在查询页面显示。最近做一个小项目,需要用到struts2标签从数据库查询数据,并且用迭代器iterator标签在查询页面显示,可是一开始,怎么也获取不到数据,想了许久,最后发现,是自己少定义了一个变量,也就是var变量。
最近做一个小项目,需要用到struts2标签从数据库查询数据,并且用迭代器iterator标签在查询页面显示,可是一开始,怎么也获取不到数据,想了许久,最后发现,是自己少定义了一个变量,也就是var变 ...
随机推荐
- DirectX11 With Windows SDK--38 级联阴影映射(CSM)
前言 在31章我们曾经实现过阴影映射,但是受到阴影贴图精度的限制,只能在场景中相当有限的范围内投射阴影.本章我们将以微软提供的例子和博客作为切入点,学习如何解决阴影中出现的Atrifacts: 边缘闪 ...
- drf认证、权限、限流
认证Authentication(5星) 认证逻辑及编写步骤 逻辑 认证类:用来校验用户是否登录,如果登录了,继续往下走,如果没有登录,直接返回 编写步骤 -第一步:写一个类,继承BaseAuthen ...
- Blazor 使用拖放(drag and drop)上传文件
在很多上传文件的应用实例中, 都可以看到[拖放文件到此上传]这种骚功能 ,今天我们就来试试Blazor能不能完成这个想法. 简述HTML5拖放 拖放是HTML5标准的一部分,任何元素都能够拖放,也能够 ...
- 001_iBase4J学习之环境搭建
目录 序言 正文 第一关.拉取项目 第二关.导入数据库 第三关.修改 JDBC 配置文件 第四关.环境搭建,修改 nginx 设置 第五关.添加地址白名单 尾声 序言 大家好,我是白墨! 本次的目标是 ...
- node.js - 路由、中间件、mysql
这几天天天搞到这么晚,我看今天的内容看起不多啊,不知道为什么学着学着就到了这么晚.今天的内容还是有点多哈,有点自我矛盾了,再次一一道来. 1. 首先今天先看到路由的概念,什么叫做路由? 路由就是映射关 ...
- B3log开源博客compose搭建
B3log开源博客搭建 docker 安装 yum install docker-ce-17.12.1.ce docker-compose 安装 curl -L https://github.com/ ...
- python练习-20200826
1:L = [ ['Apple', 'Google', 'Microsoft'], ['Java', 'Python', 'Ruby', 'PHP'], ['Adam', 'Bart','Lisa'] ...
- python学习-Day30
目录 今日内容详细 作业讲解 设计模式 单例模式 实现思想 编写 pickle模块 今日内容详细 作业讲解 编写元类规定对象的所有数据值转大写 eg: obj.name = 'jason' print ...
- 《Mybatis 手撸专栏》第7章:SQL执行器的定义和实现
作者:小傅哥 博客:https://bugstack.cn - <手写Mybatis系列> 一.前言 为什么,要读框架源码? 因为手里的业务工程代码太拉胯了!通常作为业务研发,所开发出来的 ...
- linux系统平均负载高(load average)
系统平均负载高(load average) 问题现象 两个案例都是:系统平均负载高,但cpu,内存,磁盘io都正常 什么是系统平均负载 平均负载是指单位时间内,系统处于可运行状态和不可中断状态的平均进 ...