鼎鼎知识库
您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

22.yield语句.md 3.6KB

用yield return 语句实现一个简单结合

  • HelloCollection 类包括GetEnumerator()方法。该方法的实现代码包含两条yield return语句,它们分别返回字符串Hello和World ``` using System; using System.Collections;

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;
    }
}

} ```