因此,我正在慢慢阅读一本工作手册并进入有关普查员的部分。在此期间,它给出了
的示例代码public class GameMoves
{
private IEnumerator _cross;
private IEnumerator _circle;
private int i;
public GameMoves()
{
_cross = Cross();
_circle = Circle();
i = I();
}
private int _move = 0;
const int MaxMoves = 9;
public int I()
{
Console.WriteLine("Test");
return (1);
}
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;
}
}
}
我从main方法运行它并创建此类的新实例。当构造函数运行_cross = Cross();
时,我希望它与i = I();
类似地工作,即运行类并获取返回的值。当我单步执行该程序时,它似乎根本不激活Cross()
类,而是该行创建一个值为null的枚举器。只是想知道是否有人可以解释该步骤正在做什么。感谢
答案 0 :(得分:1)
迭代器的重点正是你所看到的。迭代器应该推迟执行,直到实际使用结果。在您的代码中,I
方法不是迭代器,因此当您调用它时,它的主体将执行完成。 Cross
方法是一个迭代器,因此在使用结果之前它的主体不会被执行。
例如,如果您使用foreach
循环枚举_cross
,您会看到循环的每次迭代都会导致yield
关键字在{Cross
内被点击1}}方法。一旦命中yield break
,方法就完成了,你的循环就会退出。
作为一个很好的例子,让我们比较File.ReadAllLines
方法和File.ReadLines
方法。前者自.NET 1.0以来一直存在,而后者是后来添加的。 ReadAllLines
方法读取整个文件并将其分解为行,然后返回包含这些行的数组。这意味着在读取完整个内容之前,您无法开始处理该文件。这也意味着即使您不需要,也必须阅读全部内容。例如,如果有一百万行,并且您希望第一行包含特定单词,则即使您在第十行找到该单词,也必须读取每一行。
相比之下,ReadLines
方法是一个迭代器。在您确实需要数据之前它不会开始读取文件,它只会根据需要读取数据。这意味着您可以在读取数据时处理数据,而不是等到读取数据才开始处理。这也意味着您不必再读取所需数据,例如,如果你开始寻找一个单词并在第十行找到它,那么剩余的999,990行将不会被读取。