![]() |
1
111
但是如果你自己也在收集呢?
通常,迭代器可用于
惰性地生成一系列对象
在我看来,如果您将迭代器视为枚举集合的一种方式(这只是最简单的用例之一),那么您就错了。正如我所说,迭代器是返回序列的方法。这个序列甚至可能是 极大的 . 无法返回无限长的列表并使用前100项。信息技术 有 有时懒惰。 返回集合与返回集合生成器有很大不同 (这就是迭代器)。这是把苹果和桔子做比较。
本例打印小于10000的素数。您可以轻松地将其更改为打印少于一百万的数字,而无需接触素数生成算法。在本例中,您无法返回所有素数的列表,因为序列是无限的,消费者甚至不知道从一开始需要多少项。 |
![]() |
2
24
但是如果你没有一份清单呢?
|
![]() |
3
15
延迟计算/延迟执行任何 直到您实际调用该特定结果为止。这意味着它们也可以有效地链接在一起。突击测验:以下代码将在文件上迭代多少次?
答案恰恰是一个,而且要到下一个月才能找到答案
这除了性能之外还有其他好处。例如,我可以写一个相当简单的 通用的 方法读取和预筛选日志文件一次,并在几个不同的位置使用相同的方法,每次使用都会添加不同的筛选器。因此,我在有效地重用代码的同时保持了良好的性能。 无限列表
基本上,我使用一个迭代器块来实现斐波那契序列,该迭代器块永远不会停止(至少在到达MaxInt之前不会停止),然后以安全的方式使用该实现。
这是其中一件用散文来解释比用简单的视觉来解释更难的事情 1. :
如果您看不到该图像,它将显示相同代码的两个版本,并针对不同的关注点突出显示背景。linq代码将所有颜色很好地分组,而传统的命令式代码将颜色混合在一起。作者认为(我也同意)这个结果是使用linq和使用命令式代码的典型结果。。。linq能够更好地组织代码,使代码在各个部分之间具有更好的流。 1. 我认为这是原始来源: https://twitter.com/mariofusco/status/571999216039542784 . 还要注意的是,这段代码是Java,但C#与之类似。 |
![]() |
4
10
有时,您需要返回的序列太大,无法放入内存中。例如,大约3个月前,我参加了一个在MS SLQ数据库之间进行数据迁移的项目。数据以XML格式导出。 收益率 XmlReader . 它使编程变得相当容易。例如,假设一个文件有1000个 顾客 元素—如果您只是将此文件读入内存,则需要同时将所有元素存储在内存中,即使它们是按顺序处理的。因此,可以使用迭代器逐个遍历集合。在这种情况下,您只需为一个元素花费内存。 XmlReader 因为我们的项目是让应用程序工作的唯一方法——它工作了很长时间,但至少它没有挂起整个系统,也没有提高效率 OutOfMemoryException XmlReader 没有生成迭代器。但是迭代器让我的生活变得更加轻松(我不会那么快、毫无困难地编写导入代码)。看这个 page |
![]() |
5
9
在玩具/演示场景中,没有太大区别。但在某些情况下,生成迭代器是有用的——有时,整个列表不可用(例如,streams),或者该列表的计算成本很高,不太可能需要整个列表。 |
![]() |
6
2
|
![]() |
7
2
看看Eric White的博客(顺便说一句,非常棒的博客)上的讨论 lazy versus eager evaluation . |
![]() |
8
2
使用
您可以使用yield-returns将所有用于确定是否要对foo进行操作的逻辑放在方法内部,这样foreach循环可以更加简洁。 |
![]() |
9
2
以下是我之前对同一个问题的公认答案: 看待迭代器方法的另一种方式是,它们努力将算法“由内而外”地转换。考虑解析器。它从流中提取文本,查找其中的模式,并生成内容的高级逻辑描述。
现在,作为解析器的作者,我可以通过采用SAX方法来简化这一过程,在SAX方法中,我有一个回调接口,每当我找到模式的下一部分时都会通知它。因此,在SAX的情况下,每次我找到一个元素的开头时,我调用
但这给我的用户带来了麻烦。它们必须实现处理程序接口,因此必须编写一个响应回调方法的状态机类。这很难做到,所以最简单的方法是使用一个构建DOM树的stock实现,这样他们就可以方便地遍历树。但随后整个结构都被缓冲到内存中,这并不好。 但是我把解析器写成迭代器方法怎么样?
这并不比回调接口方法更难编写——只需返回一个从我的
用户现在可以使用foreach循环我的解析器的输出,因此他们得到了一个非常方便的命令式编程接口。 看起来他们控制住了 ,因此更容易书写和理解。 |
![]() |
10
2
使用yield的基本原因是它自己生成/返回一个列表。我们可以使用返回的列表进行进一步迭代。 |