更新记录

本文迁移自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)的更多相关文章

  1. ES6中的迭代器(Iterator)和生成器(Generator)

    前面的话 用循环语句迭代数据时,必须要初始化一个变量来记录每一次迭代在数据集合中的位置,而在许多编程语言中,已经开始通过程序化的方式用迭代器对象返回迭代过程中集合的每一个元素 迭代器的使用可以极大地简 ...

  2. 牛客网Java刷题知识点之Java 集合框架的构成、集合框架中的迭代器Iterator、集合框架中的集合接口Collection(List和Set)、集合框架中的Map集合

    不多说,直接上干货! 集合框架中包含了大量集合接口.这些接口的实现类和操作它们的算法. 集合容器因为内部的数据结构不同,有多种具体容器. 不断的向上抽取,就形成了集合框架. Map是一次添加一对元素. ...

  3. ES6中的迭代器(Iterator)和生成器(Generator)(一)

    用循环语句迭代数据时,必须要初始化一个变量来记录每一次迭代在数据集合中的位置,而在许多编程语言中,已经开始通过程序化的方式用迭代器对象返回迭代过程中集合的每一个元素 迭代器的使用可以极大地简化数据操作 ...

  4. c++中的迭代器 iterator

    迭代器iterator的作用类似于指针. iterator只有针对制定<类型>的容器才有效.例如: vector<int> vec; vector<int>::it ...

  5. ES6中的迭代器(Iterator)和生成器(Generator)(二)

    一.内建迭代器 迭代器是ES6的一个重要组成部分,在ES6中,已经默认为许多内建类型提供了内建迭代器,只有当这些内建迭代器无法实现目标时才需要自己创建.通常来说当定义自己的对象和类时才会遇到这种情况, ...

  6. Python中生成器generator和迭代器Iterator的使用方法

    一.生成器 1. 生成器的定义 把所需要值得计算方法储存起来,不会先直接生成数值,而是等到什么时候使用什么时候生成,每次生成一个,减少计算机占用内存空间 2. 生成器的创建方式 第一种只要把一个列表生 ...

  7. 如何正确遍历删除List中的元素(普通for循环、增强for循环、迭代器iterator、removeIf+方法引用)

    遍历删除List中符合条件的元素主要有以下几种方法: 普通for循环 增强for循环 foreach 迭代器iterator removeIf 和 方法引用 其中使用普通for循环容易造成遗漏元素的问 ...

  8. Python中的可迭代Iterable和迭代器Iterator

    目录 Iterable可迭代对象 如何判断对象是否是可迭代对象Iterable Iterator迭代器 如何判断对象是否迭代器Iterator 将Iterable转换成Iterator Iterabl ...

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

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

随机推荐

  1. Coursera 学习笔记|Machine Learning by Standford University - 吴恩达

    / 20220404 Week 1 - 2 / Chapter 1 - Introduction 1.1 Definition Arthur Samuel The field of study tha ...

  2. Linux磁盘之inode

    什么是 inode ? 文件储存在硬盘上,硬盘的最小存储单位叫作"扇区"(Sector).每一个扇区储存512字节(至关于0.5KB).操作系统读取硬盘的时候,不会一个个扇区地读取 ...

  3. Java基础之详谈IO流

    Java基础知识.IO流详细讲解.你所要的IO这里都有

  4. (十一)React Ant Design Pro + .Net5 WebApi:后端环境搭建-IdentityServer4(三)持久化

    一.前言 IdentityServer配合EFCore持久化,框架已经为我们准备了两个上下文: ConfigurationDbContext:配置数据(资源.客户端.身份等) PersistedGra ...

  5. 巧用 JuiceFS Sync 命令跨云迁移和同步数据

    近年来,云计算已成为主流,企业从自身利益出发,或是不愿意被单一云服务商锁定,或是业务和数据冗余,或是出于成本优化考虑,会尝试将部分或者全部业务从线下机房迁移到云或者从一个云平台迁移到另一个云平台,业务 ...

  6. 你不知道的下划线属性-text-decoration

    大家好,我是半夏,一个刚刚开始写文的沙雕程序员.如果喜欢我的文章,可以关注 点赞 加我微信:frontendpicker,一起学习交流前端,成为更优秀的工程师-关注公众号:搞前端的半夏,了解更多前端知 ...

  7. python数据处理-matplotlib入门(4)-条形图和直方图

    摘要:先介绍条形图直方图,然后用随机数生成一系列数据,保存到列表中,最后统计出相关随机数据的概率并展示 前述介绍了由点进行划线形成的拆线图和散点形成的曲线图,连点成线,主要用到了matplotlib中 ...

  8. 这样理解 HTTP,面试再也不用慌了~

    开源Linux 长按二维码加关注~ 上一篇:SSH只能用于远程Linux主机? 1 HTTP HTTP 协议是个无状态协议,不会保存状态. 2 Post 和 Get 的区别 先引入副作用和幂等的概念. ...

  9. 老生常谈系列之Aop--Spring Aop源码解析(一)

    老生常谈系列之Aop--Spring Aop源码解析(一) 前言 上一篇文章老生常谈系列之Aop--Spring Aop原理浅析大概阐述了动态代理的相关知识,并且最后的图给了一个Spring Aop实 ...

  10. linux fedora35 配置jdk,安装mysql,安装tomcat

    配置jdk18很简单,下载jdk,只需要.tar.gz结尾的文件就行,https://download.oracle.com/java/18/latest/jdk-18_linux-x64_bin.t ...