迭代器
导读
什么是迭代器
创建并使用迭代器
为整数列表创建迭代器
为泛型列表创建迭代器
什么是迭代器
迭代器(iterator)
迭代器是一种方法、get 访问器或运算符,它通过使用 yield 关键字对数组或集合类执行自定义迭代。yield 返回语句会导致源序列中的元素在访问源序列中的下一个元素之前立即返回给调用方。尽管您以方法的形式编写迭代器,但编译器会将其转换为一个实际上是状态机的嵌套类。只要客户端代码中的 foreach 循环继续进行,此类就会跟踪迭代器的位置。
注意:
若要了解编译器在后台执行了什么操作,请使用 ILDASM.exe 工具来查看为迭代器方法生成的中间语言 (IL) 代码。
将使用 foreach 语句从客户端代码中调用迭代器。例如,您可以为类创建一个迭代器,该迭代器将按相反顺序返回元素,或在迭代器返回元素之前对每个元素执行操作。在为类或结构创建迭代器时,您不必实现整个 IEnumerator 接口。当编译器检测到迭代器时,它将自动生成 IEnumerator 或 IEnumerator<(Of <(T>)>) 接口的 Current、MoveNext 和 Dispose 方法。
迭代器概述
l 迭代器是可以返回相同类型的值的有序序列的一段代码。
l 迭代器可用作方法、运算符或 get 访问器的代码体。
l 迭代器代码使用 yield return 语句依次返回每个元素。yield break 将终止迭代。
l 可以在类中实现多个迭代器。每个迭代器都必须像任何类成员一样有唯一的名称,并且可以在 foreach 语句中被客户端代码调用,如下所示:foreach(int x in SampleClass.Iterator2){}。
l 迭代器的返回类型必须为 IEnumerable、IEnumerator、IEnumerable<(Of <(T>)>) 或 IEnumerator<(Of <(T>)>)。
l 迭代器是 LINQ 查询中延迟执行行为的基础。
yield 关键字用于指定返回的一个或多个值。到达 yield return 语句时,会保存当前位置。下次调用迭代器时将从此位置重新开始执行。
迭代器对集合类特别有用,它提供一种简单的方法来迭代复杂的数据结构(如二进制树)。
示例
在本示例中,DaysOfTheWeek 类是将一周中的各天作为字符串进行存储的简单集合类。foreach 循环每迭代一次,都返回集合中的下一个字符串
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
//导入命名空间
using System.Collections;
namespace MvcUsedKeywords
{
public class DaysOfTheWeek:IEnumerable
{
string[] m_Days = { "Sun", "Mon", "Tue", "Wed", "Thr", "Fri", "Sat" };
//实现接口中的方法,创建迭代器
public IEnumerator GetEnumerator()
{
for (int i = 0; i < m_Days.Length; i++)
{
yield return m_Days[i];
}
}
}
class TestDaysOfTheWeek
{
static void Main(string[] args)
{
DaysOfTheWeek week = new DaysOfTheWeek();
foreach (string day in week)
{
Console.Write(day + " ");
}
Console.WriteLine();
}
}
}
调试下发现,foreach中每调用一次week,GetEnumerator()方法中的for循环一次,感觉是在同步进行。
运行结果: Sun Mon Tue Wed Thr Fri Sat
创建并使用迭代器
创建迭代器最常用的方法是对 IEnumerable 接口实现 GetEnumerator 方法。GetEnumerator 方法的存在使得类型成为可枚举的类型,并允许使用 foreach 语句。foreach 语句调用类中实现GetEnumerator()方法,并使用返回的枚举数来循环访问值。如下例中的创建迭代器1,创建迭代器2。
还可以使用命名的迭代器以支持通过不同的方式循环访问同一数据集合。例如,您可以提供一个按升序返回元素的迭代器,而提供按降序返回元素的另一个迭代器。迭代器还可以带有参数,以便允许客户端控制全部或部分迭代行为。如下例中的创建迭代器3。
可以在同一个迭代器中使用多个 yield 语句。如下例中的创建迭代器4。
为泛型列表创建迭代器块,要实现泛型接口 IEnumerator<T>),还要实现非泛型 GetEnumerator,因为 IEnumerable<T>) 继承自 IEnumerable。如下例中的创建迭代器5。在类名后加个类型<T>,类里声明了一个类型 T 的数组,并使用 Add 方法给数组赋值。在 GetEnumerator 方法中,使用 yield return 语句返回数组的值。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
//导入命名空间
using System.Collections;
namespace MvcUsedKeywords
{
//创建迭代器1
class ListOne
{
//实现接口IEnumerable里的GetEnumerator()方法
public IEnumerator GetEnumerator()
{
for (int i = 0; i < 10; i++)
{
yield return i;
}
}
}
//创建迭代器2
class ListTwo : IEnumerable
{
//实现接口IEnumerable里的GetEnumerator()方法
public IEnumerator GetEnumerator()
{
for (int i = 0; i < 10; i++)
{
yield return i;
}
}
}
//创建迭代器3
class ListThree
{
//使用命名的迭代器来定义,返回0-9的偶数
public IEnumerable GetEvenNumber()
{
for (int i = 0; i < 10; i = i + 2)
{
yield return i;
}
}
//使用命名的迭代器来定义,返回指定范围里的偶数
public IEnumerable GetEvenNumber(int start, int end)
{
for (int i = start; i <= end; i++)
{
yield return i;
}
}
}
//创建迭代器4
class ListFour
{
//可以在同一个迭代器中使用多个 yield 语句
public IEnumerator GetEnumerator()
{
yield return "我是";
yield return "中国人,";
yield return "我爱编程.";
yield return "你呢?";
}
}
class ListClass
{
static void Main(string[] args)
{
//利用实现接口IEnumerable里的GetEnumerator()方法
Console.Write("方式一:");
ListOne list1 = new ListOne();
foreach (int i in list1)
{
Console.Write(i + " ");
}
//利用实现接口IEnumerable里的GetEnumerator()方法
Console.Write("\n方式二:");
ListTwo list2 = new ListTwo();
foreach (int i in list2)
{
Console.Write(i + " ");
}
//调用命名的迭代器,无参数。返回0-9的偶数
Console.Write("\n调用命名的迭代器:");
ListThree list3 = new ListThree();
foreach (int i in list3.GetEvenNumber())
{
Console.Write(i+" ");
}
//调用命名的迭代器,有参数。返回指定范围里的偶数
Console.Write("\n调用命名的迭代器:");
foreach (int i in list3.GetEvenNumber(10, 20))
{
Console.Write(i + " ");
}
//调用用多个yield语句的迭代器
ListFour list4 = new ListFour();
Console.Write("\n用多个yield语句:");
foreach (string i in list4)
{
Console.Write(i);
}
}
}
}
输出:
方式一:0 1 2 3 4 5 6 7 8 9
方式二:0 1 2 3 4 5 6 7 8 9
调用命名的迭代器:0 2 4 6 8
调用命名的迭代器:10 11 12 13 14 15 16 17 18 19 20
用多个yield语句:我是中国人,我爱编程.你呢?
为整数列表创建迭代器
使用一个整数数组来构建列表。for 循环对集合进行循环访问,并返回每项的值。然后使用 foreach 循环来显示该集合的项。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
//导入命名空间
using System.Collections;
namespace MvcUsedKeywords
{
//为整数列表创建迭代器块
public class ListNum
{
public int[] items;
public ListNum()
text-align: left; margin: 0cm 0cm
分享到:
相关推荐
java 1. 泛型 2. 队列 3. 栈 4. Iterator 和 ListIterator迭代器
这个是我写的一个c语言实现的泛型和迭代器,只是简单的实现了一个链表,用long和double作为链表的元素类型. 没有实现内存释放,累了不想写了. 欢迎指正.
本文将重点介绍STL中的迭代器机制及其工作原理,帮助读者更好地理解STL的工作方式,并掌握如何有效地使用迭代器来操作容器中的元素。 #### 二、STL简介 STL(Standard Template Library)是由Alexander Stepanov、...
* `listIterator(int index)`: 返回列表中元素的列表迭代器(按适当顺序),从列表的指定位置开始。 * `add(int index, E element)`: 在列表的指定位置插入指定元素(可选操作)。 * `addAll(int index, Collection...
### C#2.0新语法扩充详解:泛型、迭代器与匿名方法 #### 泛型(Generics) 在C#2.0中引入的**泛型**是一种强大的功能,它允许开发人员创建类型安全的组件,这些组件可以用于多种数据类型而无需编写额外的代码。...
在本篇中,我们将深入探讨迭代器的源码实现,并通过一个名为“迭代器Demo”的实例来具体阐述其工作原理。 首先,让我们了解什么是迭代器。在C#中,迭代器是通过实现`IEnumerable<T>`或`IEnumerator<T>`接口来创建的...
并单独提供一个正向迭代器与反向迭代器 也提供了3种遍历方式 前中后序 参见测试用例 其维护红黑树性质的相关代码 几乎是句句含带注释 使用面向对象编程思想构建代码 并可在windows和linux下 c89标准编译通过
STL(Standard Template Library,标准模板库)是C++编程语言中的一个重要...理解并熟练使用迭代器是掌握STL的关键。在实际编程中,选择正确的迭代器类型以适应不同的容器和算法需求,可以优化代码的性能和可维护性。
此外,`IEnumerator<T>` 是泛型版本的迭代器接口,用于处理特定类型的数据。 在C#中实现迭代器模式的步骤通常如下: 1. **定义聚合对象**:创建一个类,实现 `IEnumerable` 或 `IEnumerable<T>` 接口。这些接口...
如果集合不是线程安全的,或者迭代器没有特别设计为线程安全,那么在并发环境下使用迭代器可能引发问题。如果需要在多线程环境中安全地遍历集合,可以考虑使用`java.util.concurrent`包中的并发集合类,它们提供了...
总的来说,C++的迭代器是C++标准库中实现泛型编程和容器操作的核心工具,它们为程序员提供了一种灵活且高效的方式来访问和操作容器内的元素,无论容器的内部实现如何。通过迭代器,C++实现了数据结构和算法的分离,...
1. 为什么要使用泛型? 在 Java 中,如果我们想要将一个字符串类型的值放入到集合中,这个时候,这个值放到集合之后,失去本身的类型,只能是 object 类型。如果想要对这个值进行类型转换,很容易出现类型转换错误...
泛型 , 栈 ,迭代器,队列
通过迭代器,用户可以访问容器内的元素,同时也为算法提供了统一的接口。 5. 算法:STL提供了一系列的通用算法,如sort用于排序,find用于查找,transform用于转换元素,这些算法通常与迭代器配合使用,可以在不同...
在前面的问题中,通过将函数参数从整型vector和整型值改为通用类型的vector和值,并使用迭代器,我们可以实现一个通用的`find`函数,不仅适用于vector,还适用于其他STL容器,甚至自定义的数据结构。 6. 泛型算法的...
- **`E next()`**:返回迭代器当前位置的下一个元素,并将迭代器的位置向前移动一位。 #### 迭代器的遍历流程示例 下面是一个使用迭代器遍历集合的具体示例: ```java public class Demo01Iterator { public ...
通过学习这个教程,你可以了解如何声明和使用模板,如何操作STL容器,如何运用迭代器遍历和修改元素,以及如何利用算法和仿函数优化代码。 泛型编程与STL的学习对于提升C++开发者的技能至关重要,它们能够帮助写出...
在 `main` 函数中,我们创建了一个 `MyArray` 对象,然后使用迭代器来遍历其中的元素,并将其输出到控制台上。这样,我们就可以使用迭代器来遍历容器中的元素,而不需要了解容器的内部实现。 本次实验报告展示了 ...
title: 简单迭代器 与 泛型fortags: CSDN迁移初学lua很多地方似懂非懂保存下来以后查看环境是 luaforwidows编辑器用的scite