C#-14 枚举器和迭代器
一 枚举器和可枚举类型
当我们为数组使用foreach语句时,这个语句为我们依次取出了数组中的每一个元素。
var arrInt = new int[] { 11, 12, 13, 14 };
foreach (var item in arrInt)
{
Console.WriteLine(item);
}
原因是数组实现了IEnumerable接口,接口提供了一个GetEnumerator方法可以获取一个实现了IEnumerator接口的枚举器对象。
枚举器可以依次返回请求的数组中的元素。
实现了IEnumerable接口类型叫做可枚举类型。数组是可枚举类型。
public interface IEnumerable
{
// 摘要: 返回循环访问集合的枚举器。
// 返回结果:一个可用于循环访问集合的 System.Collections.IEnumerator 对象。
IEnumerator GetEnumerator();
}
foreach语句设计用来和可枚举类型一起使用。只要给它的遍历对象是可枚举类型,它就会执行如下行为:
- 通过调用GetEnumerator方法获取对象的枚举器;
- 从枚举器中请求每一项并把它作为迭代变量。
二 IEnumerator接口
IEnumerator接口的定义如下:
public interface IEnumerator
{
// 摘要:获取集合中位于枚举数当前位置的元素
// 返回结果:集合中位于枚举数当前位置的元素。
object Current { get; }
// 摘要:将枚举数推进到集合的下一个元素。
// 返回结果:如果枚举数已成功地推进到下一个元素,则为 true;如果枚举数传递到集合的末尾,则为 false。
// 异常:T:System.InvalidOperationException:创建枚举器后,已修改该集合。
bool MoveNext(); // 摘要:将枚举数设置为其初始位置,该位置位于集合中第一个元素之前。
// 异常: T:System.InvalidOperationException: 创建枚举器后,已修改该集合。
void Reset();
}
有了枚举器,就可以使用MoveNext和Current来模仿foreach循环:
int[] arrInt = new int[] { 11, 12, 13, 14 };
foreach (var item in arrInt)
{
Console.WriteLine(item);
}
var enumerator = arrInt.GetEnumerator();
while (enumerator.MoveNext())
{
var item = (int)enumerator.Current;
Console.WriteLine(item);
}
下面是一个使用IEnumerator和IEnumerable的小例子:

class Program
{
static void Main(string[] args)
{
var myColor = new MyColors();
foreach (var item in myColor)
{
Console.WriteLine(item);
}
}
} class ColorEnumeraotr : IEnumerator
{
string[] _colors;
int _position = -1; public ColorEnumeraotr(string[] theColors)
{
_colors = new string[theColors.Length];
for (int i = 0; i < theColors.Length; i++)
{
_colors[i] = theColors[i];
}
} public object Current
{
get
{
if (_position == -1)
throw new InvalidOperationException();
if (_position >= _colors.Length)
throw new InvalidOperationException(); return _colors[_position];
}
} public bool MoveNext()
{
if (_position < _colors.Length - 1)
{
_position++;
return true;
}
return false;
} public void Reset()
{
_position = -1;
}
} class MyColors : IEnumerable
{
string[] Colors = new string[] { "red","blue","yellow","green","white"}; public IEnumerator GetEnumerator()
{
return new ColorEnumeraotr(Colors);
}
}
三 泛型枚举接口
非泛型接口的实现不是类型安全的,它返回object的引用,然后必须转化为实际类型。
所以实际上,在多数情况下,我们应该使用泛型版本的IEnumerable<T>和IEnumerator<T>。
泛型接口的枚举器是类型安全的,它返回实际类型的引用。
IEnumerable<T>接口的GetEnumerator方法返回实现IEnumerator<T>的枚举器对象。
实现IEnumerator<T>的枚举器类的Current属性,它返回T类型的对象。
四 迭代器
C#从2.0版本开始提供了更简单的创建枚举器和可枚举类型的方式。这种结构叫做迭代器。
迭代器块是有一个或多个yield语句的代码块。
迭代器块与其他代码块不同。其他块包含的语句是命令式的,也就是块中的语句依次执行,最后离开块。
而迭代器块是描述了希望编译器为我们创建的枚举器类的行为,迭代器块中的代码描述了如何枚举元素。
迭代器块有两个特殊语句:
- yield return : 指定了序列中返回的下一项;
- yield break : 指定在序列中没有其他项。
//产生枚举器的迭代器
public IEnumerator<string> IteratorMethod1()
{
yield return "red";
yield return "blue";
yield return "yellow";
} //产生可枚举类型的迭代器
public IEnumerable<string> IteratorMethod2()
{
yield return "red";
yield return "blue";
yield return "yellow";
}
4.1 使用迭代器来创建枚举器
下面代码演示如何使用迭代器来创建枚举器:

class Program
{
static void Main(string[] args)
{
var mc = new MyClass();
foreach (var item in mc)
{
Console.WriteLine(item);
}
}
} class MyClass
{
public IEnumerator<string> GetEnumerator()
{
return MyEnumerator(); //返回枚举器
} //迭代器
public IEnumerator<string> MyEnumerator()
{
yield return "red";
yield return "blue";
yield return "yellow";
}
}
4.2 使用迭代器来创建可枚举类型
下面代码演示如何使用迭代器来创建可枚举类型:

class Program
{
static void Main(string[] args)
{
var mc = new MyClass();
foreach (var item in mc)
{
Console.WriteLine(item);
} foreach (var item in mc.MyEnumerable())
{
Console.WriteLine(item);
}
}
} class MyClass
{
public IEnumerator<string> GetEnumerator()
{
IEnumerable<string> myEnumerable = MyEnumerable();
return myEnumerable.GetEnumerator();
} public IEnumerable<string> MyEnumerable()
{
yield return "red";
yield return "blue";
yield return "yellow";
}
}
C#-14 枚举器和迭代器的更多相关文章
- C#图解教程 第十八章 枚举器和迭代器
枚举器和迭代器 枚举器和可枚举类型 foreach语句 IEnumerator接口 使用IEnumerable和IEnumerator的示例 泛型枚举接口迭代器 迭代器块使用迭代器来创建枚举器使用迭代 ...
- C# 枚举器和迭代器
一.枚举器(enumerator)和可枚举类型(enumeration) 我们都知道foreach语句可以用来遍历数组中的元素,但你有没有想过为什么它可以被foreach处理呢? 这是因为数组可以按需 ...
- 设计模式 - 适配器模式(adapter pattern) 枚举器和迭代器 具体解释
适配器模式(adapter pattern) 枚举器和迭代器 具体解释 本文地址: http://blog.csdn.net/caroline_wendy 參考适配器模式(adapter patter ...
- C#知识点-枚举器和迭代器
一.几个基本概念的理解 问题一:为什么数组可以使用foreach输出各元素 答:数组是可枚举类型,它实现了一个枚举器(enumerator)对象:枚举器知道各元素的次序并跟踪它们的位置,然后返回请求的 ...
- 【Unity|C#】基础篇(20)——枚举器与迭代器(IEnumerable/IEnumerator)
[学习资料] <C#图解教程>(第18章):https://www.cnblogs.com/moonache/p/7687551.html 电子书下载:https://pan.baidu. ...
- C#枚举器/迭代器
一.枚举器 1.为什么foreach可以顺序遍历数组? 因为foreach可以识别可枚举类型,通过访问数组提供的枚举器对象来识别数组中元素的位置从而获取元素的值并打印出来. 2.什么是枚举器?可枚举类 ...
- C#中的枚举器(转)
术语表 Iterator:枚举器(迭代器) 如果你正在创建一个表现和行为都类似于集合的类,允许类的用户使用foreach语句对集合中的成员进行枚举将会是很方便的.这在C# 2.0中比 C# 1.1更容 ...
- 【转】C#学习之用迭代器实现枚举器
http://www.cnblogs.com/zouzf/archive/2012/02/22/2362954.html 本人初学C#,本文仅供个人整理思路用,那里说得不对,请大家多多指教,万分感激! ...
- ruby迭代器枚举器
迭代器一个迭代器是一个方法,这个方法里面有yield语句,使用了yield的方法叫做迭代器,迭代器并非一定要迭代,与传递给这个方法的块进行数据传输 yield将数据传给代码快,代码块再把数据传输给yi ...
随机推荐
- 队列Q_via牛客网
题目 链接:https://ac.nowcoder.com/acm/contest/28537/L 来源:牛客网 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 262144K,其他语 ...
- this关键字和构造方法
构造方法: 构造方法的定义:构造方法是类的一个特殊成员,它会在类实例化对象的时候被自动调用 作用:可以在实例化对象的同时对这个对象的属性进行赋值 案例:Student student = new St ...
- Clickhouse 实现 MaterializedPostgreSQL
Clickhouse 实现 MaterializedPostgreSQL 开发环境:macOS 12.4 + docker 一.环境搭建 docker-compose.yml services: po ...
- 多线程与高并发(五)—— 源码解析 ReentrantLock
一.前言 ReentrantLock 是基于 AQS 实现的同步框架,关于 AQS 的源码在 这篇文章 已经讲解过,ReentrantLock 的主要实现都依赖AQS,因此在阅读本文前应该先了解 AQ ...
- springmvc静态资源配置
<servlet> <servlet-name>dispatcher</servlet-name> <servlet-class>org.springf ...
- 使用 Java 操作 Redis
Jedis 1. 概述 Jedis 是一款使用 Java 操作 Redis 的工具,有点类似于 JDBC 2. 引入依赖 <dependency> <groupId>redis ...
- [HDU6057] Kanade‘s convolution (FWT)
题面 出自HDU6057 给你两个数列 A [ 0... 2 m − 1 ] A[0...2^m-1] A[0...2m−1] 和 B [ 0... 2 m − 1 ] B[0...2^m-1] B[ ...
- MixCSE:困难样本在句子表示中的使用
Unsupervised Sentence Representation via Contrastive Learning with Mixing Negatives 论文地址:https://www ...
- 往harbor上传镜像
下载镜像并给镜像打tag [root@hdss7-200 harbor]# docker pull nginx:1.7.9 [root@hdss7-200 harbor]# docker images ...
- Windows 11 新材质 Mica Alt 效果展示
本文是 WinUI 3 踩坑记 的一部分,该系列发布于 GitHub@Scighost/WinUI3Keng,若内容出现冲突以 GitHub 上的为准. 微软在 2022-09-02 更新了官方文档, ...