ISerialized .Net, C#, Scrum and agile software development

6Jan/1016

A quick start guide to yield return and yield break

The yield statement was introduced in .Net 2.0, but I am a bit surprised that I meet many senior developers who has never used yield return (and yield break)! For some strange reason, yield has become some kind of hidden treasure in .Net. Through this post, I hope I can show some simple examples, and give some of the ideas, benefits and limitations with yield.

First up, what is yield? Yield is used to return an IEnumerable from eg. a loop within a method. For example, if I have a method that I want to return several values from, I could do it in the following way:

public static List<int> GetResultList()
{
    var l = new List<int>();
    for (int i = 0; i < 100; i++)
    {
        l.Add(i);
    }
    return l;
}

Here I create a generic list of integers, which I poplulate, before I return the full list, it works fine, and I guess thats why many developers never started using it! To create a similar functionality with yield, returning an IEnumerable, I can do the following:

public static IEnumerable<int> GetResult()
{
    for (int i = 0; i < 100; i++)
    {
        yield return i;
    }
}

I get rid of some unnecessary code, and its easier to see what I actually want to return! If I inside this loop want to abort the iteration and return, I do this through the yield break. The yield break, will do more than a normal break, as it will return from the method, and not only from the for-loop. Eg: If I have to consecutive for-loops in the same method, both using yield, and I do yield break in the first, the second for-loop will never be executed:

public static IEnumerable<string> GetMoreResults()
{
    for (int i = 0; i < 20; i++)
    {
        yield return "Value " + i;
        yield break;
    }

    //Do something else

    for (int i = 0; i < 20; i++)
    {
        yield return "Another value " + i;
    }
}

Here I will only get one value returned in my IEnumerable, as the yield break will end the method execution.

If you have written a couple of methods using yield return, you might  have noticed, is that the debugger will never step into a method containing a yield return, and you can not use yield return in combination with try/catch. This is due to the fact that the iterator blocks uses deferred execution, meaning that it is not actually executed until you start iterating (using the IEnumerable).

Happy coding! 

Posted by Pål Eie

Comments (16) Trackbacks (0)
  1. Excellent concise summary! Thank you – did not know about the deferred nature of yield return.

  2. Thanks! I appreciate the feedback!

    The deferred nature is very useful, when I discovered this feature it suddenly made sense to me that I was not able to debug a yield method.

  3. Great, precisely explained in a couple of words. Thanks. Not to compare with verbose and erroneous explanation in msdn.. Or, do I oversee something?

  4. This summarize my experiences amd gives and brief but concise summary of the essentials from MSDN! Great to hear that you like my blog! I allways appreciate feedback!

  5. Hey a nice post…. really helped me in understanding the yield thing

  6. Very nice and easy to understand explanation for bigginers..Thanks

  7. Simply superb. Keep writing…

  8. Just a quick note: in my experience the debugger will enter a yield method, but only when it is executed; i.e. when you iterate over the IEnumerable. This is because of deferred execution, as you state.

    Perhaps this is what you meant anyway, but I thought it worth clarifying.

  9. Hi JT!

    You are absolutely right! The deferred execution results in the behavior you describe: The method will not execute until you actually use the data from it, eg. through an iteration and then the debugger will also be able to enter the method.

    Thanks for the clarification on this!

  10. Excellent!… Very nicely explained. Keep writing on such hidden treasures of .NET.

  11. And thanks to JT to for clarification on deferred execution :)

  12. Thanks, I didn’t know about the deferred execution!

  13. copied from python…how shameful

  14. There are so many things in .Net that are rip-offs from other frameworks! :)

  15. Nice on and easy to understand

  16. Your post and JT’s response explains clearly the unusual debugging behaviour when yield return is invovled – deferred execution.

    Thanks.


Leave a comment

No trackbacks yet.