产量无法理解功能
本文关键字:功能 | 更新日期: 2023-09-27 18:37:28
首先,我已经搜索过这个,但我仍然无法理解何时使用 yield。
例如,我有以下代码:
string[] days = { "Sun", "Mon", "Tue", "Wed", "Thr", "Fri", "Sat" };
public System.Collections.IEnumerator GetEnumerator()
{
for (int i = 0; i < days.Length; i++)
{
yield return days[i];
}
}
上面的代码和下面的代码有什么区别?
string[] days = { "Sun", "Mon", "Tue", "Wed", "Thr", "Fri", "Sat" };
public System.Collections.IEnumerator GetEnumerator()
{
for (int i = 0; i < days.Length; i++)
{
return days[i];
}
}
你能告诉我什么时候使用产量吗?
return
方法不记得你在数组中的位置。每次使用它时,它都会返回星期日,仅仅是因为它每次都从零开始循环。
使用yield
更多(至少在概念上)"我会返回这个值,但是,下次你打电话给我时,我会从我离开的地方(在循环内)继续"。
C 中也可以做类似的事情,使用静态变量来记住你在哪里:
char *nextDay () {
static char *days[] = { "Sun", "Mon", "Tue", "Wed", "Thr", "Fri", "Sat" };
static int nextDay = -1;
nextDay = (nextDay + 1) % (sizeof (days) / sizeof (*days));
return days[nextDay];
}
nextDay
变量在函数调用期间保持的事实意味着它可以用于循环遍历数组。
C# 中的某些构造将导致编译器将代码转换为非常不同的代码。 yield return
语句会导致这种转换。 看起来像执行yield return
的函数实际上被编译成一个类;函数中的许多局部变量都转换为类字段。 类本身通常会实现IEnumerable<T>
和IEnumerator<T>
。 第一次调用MoveNext
时,类代码将运行函数的部分直到第一个yield return
,并跟踪它命中了哪个yield return
。 下次调用它时,它将在那里开始执行并运行,直到调用下一个yield return
。 如果有任何Try/Finally
块,则Finally
块中的代码部分将执行以响应IDisposable.Dispose
。
实际效果是,C# 编译器为迭代器生成的代码看起来与程序员编写的代码几乎完全不同。 看起来yield return
不可能做到的原因是,它的行为对于任何甚至远程类似于方法调用的函数都是不可能的,但是编译器将任何包含yield return
的函数转换为其行为甚至远不类似于方法调用的类。
Yield 与 foreach-loops 和 for 循环交互。它允许仅在需要时生成foreach循环或for循环中的每个迭代。通过这种方式,它可以提高性能。
可以在此处找到产量及其好处的完整解释:
http://www.ytechie.com/2009/02/using-c-yield-for-readability-and-performance.html