windows C#-迭代器(下)

embedded/2024/11/30 3:03:04/
对泛型列表使用迭代器

在以下示例中,Stack<T> 泛型类实现 IEnumerable<T> 泛型接口。 Push 方法将值分配给类型为 T 的数组。 GetEnumerator 方法通过使用 yield return 语句返回数组值。

除了泛型 GetEnumerator 方法,还必须实现非泛型 GetEnumerator 方法。 这是因为从 IEnumerable 继承了 IEnumerable<T>。 非泛型实现遵从泛型实现的规则。

本示例使用命名迭代器来支持通过各种方法循环访问同一数据集合。 这些命名迭代器为 TopToBottom 和 BottomToTop 属性,以及 TopN 方法。

BottomToTop 属性在 get 访问器中使用迭代器。

static void Main()
{Stack<int> theStack = new Stack<int>();//  Add items to the stack.for (int number = 0; number <= 9; number++){theStack.Push(number);}// Retrieve items from the stack.// foreach is allowed because theStack implements IEnumerable<int>.foreach (int number in theStack){Console.Write("{0} ", number);}Console.WriteLine();// Output: 9 8 7 6 5 4 3 2 1 0// foreach is allowed, because theStack.TopToBottom returns IEnumerable(Of Integer).foreach (int number in theStack.TopToBottom){Console.Write("{0} ", number);}Console.WriteLine();// Output: 9 8 7 6 5 4 3 2 1 0foreach (int number in theStack.BottomToTop){Console.Write("{0} ", number);}Console.WriteLine();// Output: 0 1 2 3 4 5 6 7 8 9foreach (int number in theStack.TopN(7)){Console.Write("{0} ", number);}Console.WriteLine();// Output: 9 8 7 6 5 4 3Console.ReadKey();
}public class Stack<T> : IEnumerable<T>
{private T[] values = new T[100];private int top = 0;public void Push(T t){values[top] = t;top++;}public T Pop(){top--;return values[top];}// This method implements the GetEnumerator method. It allows// an instance of the class to be used in a foreach statement.public IEnumerator<T> GetEnumerator(){for (int index = top - 1; index >= 0; index--){yield return values[index];}}IEnumerator IEnumerable.GetEnumerator(){return GetEnumerator();}public IEnumerable<T> TopToBottom{get { return this; }}public IEnumerable<T> BottomToTop{get{for (int index = 0; index <= top - 1; index++){yield return values[index];}}}public IEnumerable<T> TopN(int itemsFromTop){// Return less than itemsFromTop if necessary.int startIndex = itemsFromTop >= top ? 0 : top - itemsFromTop;for (int index = top - 1; index >= startIndex; index--){yield return values[index];}}}
语法信息

迭代器可用作一种方法,或一个 get 访问器。 不能在事件、实例构造函数、静态构造函数或静态终结器中使用迭代器。

必须存在从 yield return 语句中的表达式类型到迭代器返回的 IEnumerable<T> 类型参数的隐式转换。

在 C# 中,迭代器方法不能有任何 in、ref 或 out 参数。

在 C# 中,yield 不是保留字,只有在 return 或 break 关键字之前使用时才有特殊含义。

技术实现

即使将迭代器编写成方法,编译器也会将其转换为实际上是状态机的嵌套类。 只要客户端代码中的 foreach 循环继续,此类就会跟踪迭代器的位置。

若要查看编译器执行的操作,可使用 Ildasm.exe 工具查看为迭代器方法生成的公共中间语言代码。

为类或结构创建迭代器时,不必实现整个 IEnumerator 接口。 编译器检测到迭代器时,会自动生成 IEnumerator 或 IEnumerator<T> 接口的 Current、MoveNext 和 Dispose 方法。

在 foreach 循环(或对 IEnumerator.MoveNext 的直接调用)的每次后续迭代中,下一个迭代器代码体都会在上一个 yield return 语句之后恢复。 然后继续下一个 yield return 语句,直至到达迭代器体的结尾,或直至遇到 yield break 语句。

迭代器不支持 IEnumerator.Reset 方法。 若要从头开始重新迭代,必须获取新的迭代器。 在迭代器方法返回的迭代器上调用 Reset 会引发 NotSupportedException。

迭代器的使用

需要使用复杂代码填充列表序列时,使用迭代器可保持 foreach 循环的简单性。 需执行以下操作时,这可能很有用:

在第一次 foreach 循环迭代之后,修改列表序列。

避免在 foreach 循环的第一次迭代之前完全加载大型列表。 一个示例是用于加载一批表格行的分页提取。 另一个示例是 EnumerateFiles 方法,该方法在 .NET 中实现迭代器。

在迭代器中封装生成列表。 使用迭代器方法,可生成该列表,然后在循环中产出每个结果。


http://www.ppmy.cn/embedded/141635.html

相关文章

std库锁机制的使用

在多线程编程中,关键资源的读写访问是程序员需要非常重视的部分。而控制好读写主要靠的就是锁机制,在各个编程框架中都提供了锁的实现机制。这一篇就简单列举一下std标准库中提供的一些锁机制。 锁是干什么用的 这里稍微啰嗦一句,用通俗的话解释一下锁是干什么用的。其实我…

2024年第十三届”认证杯“数学中国数学建模国际赛(小美赛)

↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓

【JavaEE初阶 — 网络编程】TCP流套接字编程

TCP流套接字编程 1. TCP &#xff06; UDP 的区别 TCP 的核心特点是面向字节流&#xff0c;读写数据的基本单位是字节 byte 2 API介绍 2.1 ServerSocket 定义 ServerSocket 是创建 TCP 服务端 Socket 的API。 构造方法 方法签名 方法说明 ServerS…

Mybatis集成篇(一)

Spring 框架集成Mybatis 目前主流Spring框架体系中&#xff0c;可以集成很多第三方框架&#xff0c;方便开发者利用Spring框架机制使用第三方框架的功能。就例如本篇Spring集成Mybatis 简单集成案例&#xff1a; Config配置&#xff1a; Configuration MapperScan(basePack…

Git远程仓库过大导致clone失败的解决方法

方法1. 升级为git 最新版本 方法2&#xff1a; 浅层clone 首先clone一层&#xff1a; 1$ git clone --depth1 http://xxx.git浅层clone成功后&#xff0c;再完整拉取&#xff1a; 1 2 3$ git fetch --unshallow # 拉取完整当前分支 $ git remote set-branches origin * # 追…

架构第十八章:jenkins

CI&CD: 持续集成注重将各个开发者的工作集合到一个代码仓库中&#xff0c;通常每天会进行几次&#xff0c; 主要目的是尽早发现集成错误&#xff0c;使团队更加紧密结合&#xff0c;更好地协作。 持续交付的目的是最小化部署或发布过程中团队固有的摩擦&#xff0c; 它的实…

iphone小程序设置burpsuite代理抓包

1、iphone、burpsuite链接同一wifi 2、burpsuite设置代理 3、iphone配置代理 4、浏览器访问“http://burp”&#xff0c;下载证书&#xff0c;安装证书 5、前往“设置”>“通用”>“关于本机”>“证书信任设置”。 在“针对根证书启用完全信任”下&#xff0c;开启对…

类和对象--中--运算符重载、日期类实现(重要)

目录 1.运算符重载 2.日期类 1.运算符重载 2.1作用&#xff1a; 为了让C的新类型&#xff1a;类。也可以进行内置类型的运算符操作。所以就有了运算符重载。 2.2定义&#xff1a; 运算符重载是具有特殊名字的函数&#xff0c;他的名字是由operator和后⾯要定义的运算符共…