- Yield是C#为方便提供枚举对象的一种语法,上一篇,我介绍了IEnumerator接口的用法.要求实现类通过MoveNext()来不断的查找下一个元素,利用Yield可以更方便灵活的使用IEnumerator接口,看Demo(不看上一篇,直接看这一篇,会有理解上的困难)
class StudentsYield
{
string[] studentnames = new string[] { "wang", "li", "meng" };
public IEnumerator TestYieldFun()
{
int index = 0;
while (index <= studentnames.Length - 1)
{
Console.WriteLine("开始执行枚举代码:"+ studentnames[index]);
yield return studentnames[index];
index++;
}
index = 0;
}
}
- 上面的代码中,StudentYield并没有实现IEnumerator接口,但提供了一个方法来返回一个枚举对象,但代码中,没有发现显示的返回对象的语句,此时,就是yield return在起作用了
当通过该方法获取到 枚举对象时,你确实得到了一个枚举对象,然后
为这个对象执行MoveNext()方法,和正常的用法是一样,此时,就会执行TestYieldFun()这个方法,执行到yield语句停止,然后把return的对象赋值给Current属性,然后MoveNext()方法跳出
- 第二次,再为这个枚举对象执行MoveNext()方法时,因为这个枚举对象保存了之前的状态,所以,代码会从yield
turn开始继续向下执行,直到下一次碰到yield
return,那么继续给Currnet赋值,或者跳出TestYieldFun()这个方法,使用MoveNext()返回false来结束这个遍历行为 - 当然,你可以在代码中使用yield break来直接使MoveNext()返回false来结束 说白了,yield
就是一种方便我们写出灵活的枚举对象的一种写法.
通过下面这个Demo,加深一下理解吧,这个Demo会交替打印Cross和Circle中的内容,复制粘到VS上,可以直接跑起来看一下
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 {0}", _move);
if (++_move >= MaxMoves)
yield break;
yield return _cross;
}
}
}
//入口
static void Main()
{
var game = new GameMoves();
//这句代码,将game.Cross()替换成game.cross,看看有啥不同,理解了这个,才说明真正明白了
IEnumerator enumerator = game.Cross();
while (enumerator.MoveNext())
{
enumerator = enumerator.Current as IEnumerator;
}
}
下一篇,将理解Unity如何利用这个接口实现协程的