很多时候我们需要收集一些根据确定条件产生的结果。为此我们需要创建一些集合对象,插入输出到这些集合,最后返回集合。但是这样做是很烦人的。
有一个简单的方式去做这些,就是使用yield语句(先前C#2.0)。这个关键字被用来在一个方法中从一个循环返回元素,并且多次调用时保留方法的状态。
Yield返回Ienumerator 或者泛型Ienumerator<T>。
public
static
IEnumerator
<
int
>
GetCounter()
{
for
(
int
count
=
0
; count
<
10
; count
++
)
{
yield
return
count;
}
}
这将返回集合
IEnumerator<int>
,可以用来获取返回的对象。
IEnumerator
<
int
>
list
=
GetCounter();
Console.Write(list.MoveNext()
+
"
"
+
list.Current);
还可以有yield break语句。如果在一个方法中yield break语句被执行到,这个方法的执行将被停止没有返回。使用这样,第一个方法可以被重写如下
public
static
IEnumerator
<
int
>
GetCounter()
{
int
max
=
10
, min
=
5
;
while
(
true
)
{
if
(min
>=
max)
{
yield
break
;
}
yield
return
min
++
;
}
}
在我更深入之前,值得记住在一个迭代程序块中不仅仅是从开始到结束的运行。当方法被最初调用时,迭代才刚刚被创建。它只在MoveNext()被调用的时候才执行。在那个时候,如平时一样从方法的开头执行,直到处理到第一个yield return 或者 yield break语句抑或是到达方法的结尾。在那个时候,一个Boolean值被返回来显示语句块是否完成迭代。如果或者当MoveNext()被再次调用的话,方法将仅仅从yield return语句之后继续执行。在每个和所有MoveNext()函数中,迭代函数将被调用,并且将从上一次的yield开始执行到下一次yield语句。
Code
using System;
using System.Collections.Generic;
class Test
{
static readonly string Padding = new string(' ',30);
static Ienumerator<int> GetNumbers()
{
Console.WriteLine("First line of GetNumbers()");
Console.WriteLine("Just before yield return 0");
yield return 10;
Console.WriteLine("Just after yield return 0");
Console.WriteLine("Just before yield return 1");
yield return 20;
Console.WriteLine("Just after yield return 1");
}
static void Main()
{
Console.WriteLine("Calling GetNumbers()");
IEnumerator<int> iterator = GetNumbers();
Console.WriteLine("Calling MoveNext()");
Boolean more = iterator.MoveNext();
Console.WriteLine("Result={0};Current={1}",more,iterator.Current);
Console.WriteLine("Calling MoveNext() again…");
more = iterator.MoveNext();
Console.WriteLine("Result={0};Current={1}",more,iterator.Current);
Console.WriteLine("Calling MoveNext() again…");
more = iterator.MoveNext();
Console.WriteLine("Result={0} (stopping)",more);
}
}
-------Result
Calling GetNumbers()
Calling MoveNext()…
Firlst line of GetNumbers()
Just before yield return 0
Result=True;Current=10
Calling MoveNext() again…
Just after yield return 0
Just before yield return 1
Result=True;Current=20
Calling MoveNext() again…
Just after yield return 1
Result=False(stopping)
引用:http://csharpindepth.com/Articles/Chapter6/IteratorBlockImplementation.aspx
这在C#3.0中的Linq 查询表达式中很有用,它提供在Linq查询中的迭代。
假设有一个CustomerCollection 类,是一个包含一个客户列表的类
(IEnumerable<Customer> _customers)
public
class
CustomerCollection:IEnumerable
<
Customer
>
这个类被用在LINQ查询中,通过对包含在它的列表(_customers)中的客户对象来迭代,因此应该这样实现GetEnumerator方法:
public
IEnumerator
<
Customer
>
GetEnumerator()
{
foreach
(Customer customer
in
_customers)
yield
return
customer;
}
翻译自:http://munishbansal.wordpress.com/2008/09/12/yield-statement-in-c-useful-linq-statement/
这个地址可能无法访问。
Google快照地址:http://203.208.37.132/search?q=cache:egY7N3wP364J:munishbansal.wordpress.com/2008/09/12/yield-statement-in-c-useful-linq-statement/+LINQ+yield+return&cd=3&hl=zh-CN&ct=clnk&gl=cn&st_usg=ALhdy29bs1EH6irrDJSMuvjODJZXX53NPw