首先,我已经搜索了这个,但我仍然无法理解何时使用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];
}
}
你能告诉我什么时候使用收益率吗?
答案 0 :(得分:10)
return
方法不记得你在数组中的位置。每次使用它都会返回星期日,因为它每次都从零开始循环。
使用yield
更多(至少在概念上)“我会返回这个值,但是,下次你打电话给我,我会去接下我离开的地方(在循环内)”。< / p>
在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
变量的事实意味着它可以用于遍历数组。
答案 1 :(得分:4)
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
的任何函数转换为行为不具有的类。甚至远程类似于方法调用。
答案 2 :(得分:0)
产量与foreach-loops和for循环相互作用。它允许foreach-loop或for循环中的每次迭代仅在需要时生成。通过这种方式,它可以提高性能。
可以在此处找到产量及其益处的完整解释:
http://www.ytechie.com/2009/02/using-c-yield-for-readability-and-performance.html