更新记录

本文迁移自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. try、catch、finally、return的执行顺序

    1. 不管有没有异常,finally里面的语句都会执行 2. 当try和catch中有返回语句时,finally里面的语句还是会执行 3. 如果finally里面没有return语句,try和catc ...

  2. Java报错:Error creating bean with name 'testController': Injection of resource dependencies failed

    报错如下: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'testCo ...

  3. 如何让HTTPS站点评级达到A+? 还得看这篇HTTPS安全优化配置最佳实践指南

    0x00 前言简述 SSL/TLS 简单说明 描述: 当下越来越多的网站管理员为企业站点或自己的站点进行了SSL/TLS配置, SSL/TLS 是一种简单易懂的技术,它很容易部署及运行,但要对其进行安 ...

  4. Machine Learning 学习笔记 03 最小二乘法、极大似然法、交叉熵

    损失函数. 最小二乘法. 极大似然估计. 复习一下对数. 交叉熵. 信息量. 系统熵的定义. KL散度

  5. 3.初识Java

    一.Java特性和优势 简单性 面向对象 可移植性 高性能 分布式 动态性 多线程 安全性 健壮性 二.Java三大版本 一次编写到处运行 JavaSE:标准版(桌面程序,控制台开发) JavaME: ...

  6. Logistic regression中regularization失败的解决方法探索(文末附解决后code)

    在matlab中做Regularized logistic regression 原理: 我的代码: function [J, grad] = costFunctionReg(theta, X, y, ...

  7. Java语言学习day27--8月02日

    今日内容介绍1.Eclipse常用快捷键操作2.Eclipse文档注释导出帮助文档3.Eclipse项目的jar包导出与使用jar包4.不同修饰符混合使用细节5.辨析何时定义变量为成员变量6.类.抽象 ...

  8. 一行代码让你的项目轻松使用Dapr

    介绍 Dapr简化了云原生开发,让开发可以把焦点放在应用的业务逻辑上,从而让代码简单.可移植,那作为一个.Net开发者,我们也希望项目可以快速用上dapr,那究竟应该如何做呢? Dapr提出了Side ...

  9. 【面试普通人VS高手系列】Spring Boot中自动装配机制的原理

    最近一个粉丝说,他面试了4个公司,有三个公司问他:"Spring Boot 中自动装配机制的原理" 他回答了,感觉没回答错误,但是怎么就没给offer呢? 对于这个问题,看看普通人 ...

  10. Dockerfile创建自有镜像

    文件名必须名为Dockerfile,用touch命令新建Dockerfile文件(执行touch Dockerfile),Dockerfile内容: from ubuntu --基础镜像名字 main ...