public static readonly string Padding = new string(' ', 30);
public static IEnumerable<int> CreateEnumerable()
{
Console.WriteLine("{0} Start of CreateEnumerable()", Padding);
for (int i = 0; i < 3; i++)
{
Console.WriteLine("{0}About to yield {1}", Padding, i);
yield return i;
Console.WriteLine("{0}After yield", Padding);
}
Console.WriteLine("{0}Yielding final value", Padding);
yield return -1;
Console.WriteLine("{0}End of CreateEnumerable() ", Padding);
}
...
IEnumerable<int> iterable = ItratorSequence.CreateEnumerable();
IEnumerator<int> iterator = iterable.GetEnumerator();
Console.WriteLine("Starting to iterate");
while (true)
{
Console.WriteLine("Calling MoveNext()...");
bool result = iterator.MoveNext();
Console.WriteLine("... MoveNext result ={0}", result);
if (!result)
{
break;
}
Console.WriteLine("Fetching Current...");
Console.WriteLine("... Current result={0}", iterator.Current);
}
- 在第一次调用MoveNext之前,CreateEnumerable中的代码不会被调用
- 所有工作在调用MoveNext时就完成了,获取Current的值不会执行任何代码
- 在yield return的位置,代码就停止执行,在下一次调用MoveNext时又继续执行
- 在一个方法中的不同地方可以编写多个yield return语句
- 代码不会在最后的yield return处结束,而是通过返回false的MoveNext调用来结束方法的执行。
public static IEnumerable<int> CountWithTimeLimit(DateTime limit)
{
for (int i = 0; i <= 100; i++)
{
if (DateTime.Now >= limit)
{
yield break;//yield break会直接让for each 跳出
}
yield return i;
}
}
DateTime stop = DateTime.Now.AddSeconds(2);
IEnumerable<int> collection = ItratorSequence.CountWithTimeLimit(stop);
foreach (int i in collection)
{
Console.WriteLine("Received {0}", i);
Thread.Sleep(300);
}
- yield break语句终止了迭代器的运行,让当前对MoveNext的调用返回false。
public static IEnumerable<int> CountWithTimeLimit(DateTime limit)
{
try
{
for (int i = 0; i <= 100; i++)
{
if (DateTime.Now >= limit)
{
yield break;
}
yield return i;
}
}
finally
{
Console.WriteLine("Stopping!");//不管循环是否结束,这一行都回执行
}
}
- 当yield break被执行后,finally代码块里的代码就会被执行。
DateTime stop = DateTime.Now.AddSeconds(2);
IEnumerable<int> collection = ItratorSequence.CountWithTimeLimit(stop);
foreach (int i in collection)
{
Console.WriteLine("Received {0}", i);
if (i > 3)
{
Console.WriteLine("Returning");
return;
}
Thread.Sleep(300);
}
public static IEnumerable<int> CountWithTimeLimit(DateTime limit)
{
try
{
for (int i = 0; i <= 100; i++)
{
if (DateTime.Now >= limit)
{
yield break;
}
yield return i;
}
}
finally
{
Console.WriteLine("Stopping!");
}
}
- 当调用的函数return后,finally代码块里的代码也会被执行到。
- 只要调用者使用了foreach循环,迭代器块中的finally将按照你期望的方式工作。
DateTime stop = DateTime.Now.AddSeconds(2);
IEnumerable<int> collection = ItratorSequence.CountWithTimeLimit(stop);
IEnumerator<int> iterator = collection.GetEnumerator();
iterator.MoveNext();
iterator.Dispose();
- 其实是因为foreach会最终调用Dispose方法,
- 以上代码当手动调用Dispose方法时,finaly代码块里的部分也会被执行到。