Understanding how yield keyword works

If you work with C# you must know that in order to traverse a collection using the ‘foreach’ construct the collection must implement the IEnumerable interface. There’s a lot of documentation about that on the web so I won’t go into it. What I’d like to show you is an alternative to the IEnumerable interface using the ‘yield’ keyword. Take a look at this code:

public class Player
    {
        public string Name { get; set; }

        public Player(string name)
        {
            this.Name = name;
        }
    }

    public class Team
    {
        Player[] players = new Player[3];

        public Team()
        {
            players[0] = new Player("Gabriel");
            players[1] = new Player("Elisa");
            players[2] = new Player("Rafaela");
        }

        public IEnumerator GetEnumerator()
        {
            foreach (Player player in players)
            {
                yield return player;
            }
        }
    }

You can now test the code in a foreach like this:

 public static void TestYield()
        {
            Team team = new Team();
            foreach (Player player in team)
            {
                Console.WriteLine(player.Name);
            }
        }

This is really interesting, right? But how does it work? Shouldn’t the iteration through the players array start from scratch every time you call the method? Nope! This is where the magic of the yield comes in. Every time the yield is executed it will “pause the state” of the iteration and the next time the method is called it will resume the iteration from the next item. I could even rewrite my code in the following way and it would have the same effect:

public IEnumerator GetEnumerator()
        {
            yield return players[0];
            yield return players[1];
            yield return players[2];
        }

This code is only for demonstration purposes, I know that iterating the array like this wouldn’t be very smart :-) I just wanted to show you that the execution will pause.

This woks because in compile time the method using the yield will be transformed into a class which implements the IEnumerator interace and it’s stated will be maintained like any other object, that is why you get the impression the method is paused. It’s cool to understand how these things work under the hood, isn’t it?

Comments

Leave your comment

Author

Email (never displayed)

Website

Comment  
HTML is NOT allowed. Use regular line breaks and those will be respected.