15 08 2013
What can you do with yield return / yield break
Yield is another fancy keyword you will not see very often. Its only for one special usecase, but for this its very
helpful.
Imaging you want to iterate through Objects that needs to be generated or fetched from a webservice and there a thousand of
them. It may take very long to get them or they would use up so much memory you can’t even handle them.
Normaly you would have no other choise then building your own handling class and instead of iterating you just pull one
object after another.
Yield is the key to solve this problem easily. When you use yield return, you send a value back to the consumer of an
IEnumerable without leaving the code which generates the value.
But better have a look at this simple example to understand how it works:
1 2 3 4 5 |
public IEnumerable SimpleEnum() { for (int i = 0; i < 10; i++) yield return i; } |
In this example you see how yield return is used. The loop is counting from 0 to 9 and with every iteration a value is
returned to the consumer. Lets extend this simple example a little bit and have a look at the consumer.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
public static IEnumerable SimpleEnum(int count) { for (int i = 0; i < count; i++) { Thread.Sleep(300); yield return i; } } public static void Main(string[] args) { foreach (int i in SimpleEnum(10)) Console.Write("{0} ", i); Console.ReadKey(true); } |
Run this example and see whats happening.
I extended the SimpleEnum to take a parameter how many values it should return and inserted a Thread.Sleep to simulate the
long taking action. In the Main-Method you can see an easy way to consume an IEnumerable.
This foreach-loop is waiting for values to return from SimpleEnum and exits when the IEnumerable is finished.
SimpleEnum is waiting to, if the consumer takes a long time to process the value. Exchange the foreach-loop from the
example above with this one to see what i mean.
1 2 3 4 5 |
foreach (int i in SimpleEnum(10)) { Console.Write("{0} ", i); Thread.Sleep(500); } |
If you want you can add a Console.WriteLine in SimpleEnum too, to see that its waiting until the consumer is finished.
And now a brief look at yield break. Since return isn’t working without a return value, you need another way to leave the
IEnumerable-function. yield break do the trick. It leaves the IEnumerable-function immediately. You can use it when you
don’t know how many values you have to return or the returning-conditions could not be checked that easily.
For the sake of complection here a little example:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
public IEnumerable SimpleEnum(int count) { int i= 0; while(true) { i++; Thread.Sleep(300); yield return i; if (i == count) yield break; } } |
Conclusion:
yield return is a good way to generate dynamic values for an IEnumerable, for example random values or calculated ones. Its
also useful to process values that needs a long time to get or which are countless or very large.
yield return is waiting until the consumer is finished to process the next one and the consumer is waiting until the next
value is ready. Both stop working if the other one is finished.
yield break works like a return without a returning value and leaves the method immediately.
The ?? Operator (null-coalescing – Operator) Extension Methods for Strings