Reputation: 6686
I am trying to understand how yield works in C#. For testing I made some example code:
using System;
using System.Text;
namespace ConsoleApplication1
{
class GameFrame
{
};
class GameState
{
public static GameFrame Begin()
{
Console.WriteLine("GameState.Begin");
return new GameFrame();
}
public static GameFrame Play()
{
Console.WriteLine("GameState.Play");
return new GameFrame();
}
public static System.Collections.Generic.IEnumerator<GameFrame> MainLoop()
{
yield return Begin();
while (true)
{
yield return Play();
}
}
};
class Program
{
static void Main()
{
while (GameState.MainLoop() != null)
{
}
}
}
}
This code only tries to run once Begin function and call infinite times function Play. Please tell me why I never see my messages in console?
Upvotes: 2
Views: 2424
Reputation: 73502
You need to enumerate the collection, You just check whether the result is null
or not, that will not start the enumeration.
foreach (var frame in GameState.MainLoop())
{
//Do whatever with frame
}
To make it work with `foreach
you can make the MainLoop
method return IEnumerable<GameFrame>
instead of IEnumerator<GameFrame>
Or just use
var enumerator = GameState.MainLoop();
while (enumerator.MoveNext())
{
//Do whatever with enumerator.Current
}
Upvotes: 12
Reputation: 2246
GameState.MainLoop() returns IEnumerable which represents infinite collection from which you can take items. When you're using yield, elements are evaluated only when they are needed so you will see some output only if you "touch" and item
GameState.MainLoop().Take(5).ToList();
I don't recommend using foreach with infinite loops.
Upvotes: 1
Reputation: 39085
That's because you get back an IEnumerable<GameFrame>
, but never actually iterate through it.
Try this instead:
var frames = GameState.MainLoop();
foreach(var frame in frames)
{
// use the frame
// e.g. frame.Show(); (note: in your example code,
// GameFrame doesn't have any members)
}
Upvotes: 1