c# - 继续枚举 IEnumerable
问题描述
使用yield
关键字,我们只能计算IEnumerable
. 我已经设置了一个测试,其中我生成了一些项目,然后我想再生成一个。我所期望的是函数从它结束的地方开始,在这种情况下是在10000000
迭代中并且只迭代一次到10000001
. 请查看这段代码:
public static void Main()
{
var naturalNumbers = GetNaturalNumbers();
var executionTime = GetExecutionTime(() => naturalNumbers.ElementAt(10000000));
Console.WriteLine($"Time elapsed: {executionTime}");
executionTime = GetExecutionTime(() => naturalNumbers.ElementAt(10000001));
Console.WriteLine($"Time elapsed: {executionTime}");
}
public static IEnumerable<int> GetNaturalNumbers()
{
Console.WriteLine("Running GetNaturalNumbers() from the beginning");
for(int value = 0;; value++)
{
yield return value;
}
}
public static System.TimeSpan GetExecutionTime(Action action)
{
var stopwatch = Stopwatch.StartNew();
action();
stopwatch.Stop();
return stopwatch.Elapsed;
}
输出:
Running GetNaturalNumbers() from the beginning
Time elapsed: 00:00:00.0618548
Running GetNaturalNumbers() from the beginning
Time elapsed: 00:00:00.0562454
第二次调用所用的时间较短,这让我猜测这只是因为处理器优化。该函数从一开始就被调用了两次。
这个输出背后的真正原因是什么?是否可以从我们在第一次调用结束时继续迭代?
编辑:
现在我发现我的例子还不够好。假设我们在函数中有一个非常复杂且耗时的操作GetNaturalNumbers()
。我期待第二次调用从10000000
'th 元素开始枚举,而不需要再次计算所有元素。我预计第二次通话会有显着的性能提升。
另一个例子:
想象一本有很多页的书,您不想一次获得所有页面,而只想获得读者需要的数量。当读者翻页时,我们会得到它,而无需计算所有以前的。
解决方案
其他人似乎都在谈论速度,这似乎不是你真正的问题。
您正在考虑执行后:
var executionTime = GetExecutionTime(() => naturalNumbers.ElementAt(10000000));
然后执行:
executionTime = GetExecutionTime(() => naturalNumbers.ElementAt(10000001));
它应该知道你已经这样做了,10000000
所以它应该只做 1 次循环迭代。
这根本不是它的工作原理。您的 yield return 将缩短循环并返回您需要的值,但是这两个语句是完全独立的,它将运行:
for(int value = 0;; value++)
两次。
推荐阅读
- docker - 在 Intellij IDEA 中调试远程 WildFly dockerized 应用程序
- logstash - Logstash HTTP 输出插件中的 UnknownException
- java - Spring RestTemplate 链接
- python - 托管私有 Pip 存储库
- python - 单击相应的QGraphicsPixmapItem时如何打开图像?
- javascript - Tensorflow.js tf.browser.fromPixels() 必须是 HTMLVideoElement
- javascript - 网页抓取时如何获取 HTML 代码而不是源代码?
- reactjs - react如何在不同组件中使用axios实例?
- javascript - 如何将字符串数组转换为嵌套的 JSON 对象?
- mysql - 来自 django ORM 的单个对象值