用yield return 语句实现一个简单结合
namepace Wrox.ProCSharp.Arrays {
public class HelloCollection
{
public IEnumerator<string>GetEnumerator()
{
yield return"HEllo";
yield return "World";
}
}
} 现在可以用foreach语句迭代集合 public void HelloWord() {
var helloCollection=new HelloCollection();
foreach(var s in helloCollection)
{
WriteLine(s);
}
}
-包含yield 语句的方法或属性也称为迭代块。迭代块必须声明为返回IEnumerator或IEnumerable接口,或者这些接口的泛型版本,这个块可以包含多条yield return语句或yield break 语句,但不能包含return语句。
- 下面例子,可以把yield类型看做内部类Enumerator。外部类的GEtEnumerator()方法实例化并返回一个新的yield类型。在yield类型中,变量state定义了迭代的当前位置,每次调用MoveNext()时,当前位置都会改变。MoveNext()封装了迭代块的代码,并设置了current变量的值,从此使Current属性根据位置返回一个对象。
public class HelloCollection {
public IEnumerator GetEnumerator()=>new Enumerator(0);
public class Enumerator :IEnumerator<string>,IEnumerator,IDisposable
{
private int_state;
private string _current;
public Enumerator(int state)
{
_state =state;
}
bool System.Collections.IEnumerator.MoveNext()
{
switch(state)
{
case 0:
_current="Hello";
_state=1;
return true;
case 1:
_current="World";
_state=2;
return true;
case 2:
break;
}
return false;
}
void System.Collections.IEnumerator.Reset()
{
throw new NotSupportedException();
}
string System.Collections.Generic.IEnumerator<string>.Current=>current;
void IDisposable.Dispose()
{}
}
}
> 用yield return 返回枚举器
- 例子说明:在Tic-Tac-Toe 游戏中有9个域,玩家轮流在这些域中放置一个“十”字或一个圆。这些移动操作由GameMoves类模拟。方法Cross()和Circle()是创建迭代类型的迭代块。在Cross()迭代块中,将移动操作的信息写到控制台上,并递增移动次数。如果移动次数大于8,就用yield break停止迭代;否则,就在每次迭代中返回yield类型circle的枚举对象。Circle()迭代块非常类似于Cross()迭代块,知识它在每次迭代中返回cross迭代器类型
public class GameMoves {
private IEnumerator _cross;
private IEnumerator _circle;
public GameMoves()
{
_cross=Cross();
_circle=Circle();
}
private int _move=0;
const int MAxMoves=9;
public IEnumerator Cross()
{
while (true)
{
WriteLine($"Cross,move {_move}");
if(++_move >=MaxMoves)
{
yield break;
}
yield return _circle;
}
}
public IEnumerator Circle()
{
while(true)
{
WriteLine($"Circle,move{move}");
if(++_move>=MaxMoves)
{
yield break;
}
yield return _cross;
}
}
} ```