在 C# 中使用 IEnumerator
Working of IEnumerator in c#
static void Main()
{
DaysOfTheWeek days = new DaysOfTheWeek();
foreach (string day in days)
{
Console.Write(day + " ");
}
// Output: Sun Mon Tue Wed Thu Fri Sat
Console.ReadKey();
}
public class DaysOfTheWeek : IEnumerable
{
private string[] days = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
public IEnumerator GetEnumerator()
{
for (int index = 0; index < days.Length; index++)
{
// Yield each day of the week.
yield return days[index];
}
}
}
foreach 循环中发生了什么。它是否为每次迭代调用 GetEnumerator 函数,或者 foreach 被 GetEnumerator 函数替换?在这种情况下,复杂度是否达到 O(n2)?
yield return
创建一个状态机,基本上 returns 一个值,然后等待调用方(您的第一个 foreach
)请求枚举器中的下一个项目。
IEnumerable
只是一个接口,描述了一种迭代一组数据的方法,其中的IEnumerator
是描述如何调用迭代器的接口。
此博客 yield return
中有一个很好的描述 post:
https://www.kenneth-truyers.net/2016/05/12/yield-return-in-c/
基本上它说
Each iteration of the foreach loop calls the iterator method. When the yield return statement is reached the value is returned, and the current location in code is retained. Execution is restarted from that location the next time that the iterator function is called.
由于位置是为下一次调用保留的,我认为复杂度应该是O(n)而不是O(n2)。
不,不会为每次迭代调用 GetEnumerator。如果您在发布配置中编译代码并检查生成的 IL 代码,您最终会得到这样的代码。
IEnumerator enumerator2 = days.GetEnumerator();
try
{
while (enumerator2.MoveNext())
{
Console.Write((string)enumerator2.Current + " ");
}
}
finally
{
IDisposable disposable = enumerator2 as IDisposable;
if (disposable != null)
{
disposable.Dispose();
}
}
所以基本上您可以自己编写相同的代码,foreach 只是帮助您编写更少代码的语法糖。
static void Main()
{
DaysOfTheWeek days = new DaysOfTheWeek();
foreach (string day in days)
{
Console.Write(day + " ");
}
// Output: Sun Mon Tue Wed Thu Fri Sat
Console.ReadKey();
}
public class DaysOfTheWeek : IEnumerable
{
private string[] days = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
public IEnumerator GetEnumerator()
{
for (int index = 0; index < days.Length; index++)
{
// Yield each day of the week.
yield return days[index];
}
}
}
foreach 循环中发生了什么。它是否为每次迭代调用 GetEnumerator 函数,或者 foreach 被 GetEnumerator 函数替换?在这种情况下,复杂度是否达到 O(n2)?
yield return
创建一个状态机,基本上 returns 一个值,然后等待调用方(您的第一个 foreach
)请求枚举器中的下一个项目。
IEnumerable
只是一个接口,描述了一种迭代一组数据的方法,其中的IEnumerator
是描述如何调用迭代器的接口。
此博客 yield return
中有一个很好的描述 post:
https://www.kenneth-truyers.net/2016/05/12/yield-return-in-c/
基本上它说
Each iteration of the foreach loop calls the iterator method. When the yield return statement is reached the value is returned, and the current location in code is retained. Execution is restarted from that location the next time that the iterator function is called.
由于位置是为下一次调用保留的,我认为复杂度应该是O(n)而不是O(n2)。
不,不会为每次迭代调用 GetEnumerator。如果您在发布配置中编译代码并检查生成的 IL 代码,您最终会得到这样的代码。
IEnumerator enumerator2 = days.GetEnumerator();
try
{
while (enumerator2.MoveNext())
{
Console.Write((string)enumerator2.Current + " ");
}
}
finally
{
IDisposable disposable = enumerator2 as IDisposable;
if (disposable != null)
{
disposable.Dispose();
}
}
所以基本上您可以自己编写相同的代码,foreach 只是帮助您编写更少代码的语法糖。