Yield (advanced)

The yield statement is used in iterator blocks to yield a value or signal the end of an iteration. You don’t need to create instances of IEnumerable or IEnumerator, it is all implied in the yield statement. There are only two ways to use yield:
yield return returns the next value, yield break signals the end of values.

static IEnumerable<int> Range() {    
    for (int i = 0; i < 100; i++) {
        yield return i;
        if (i == 6) yield break;
    }
} //

static public void Test() {
    foreach (int i in Range()) { Console.WriteLine(i); }
} //

example output:
0
1
2
3
4
5
6

There is one issue here. I placed the line “if (i == 6) yield break;” after “yield return i;” on purpose. Only then you can see that the loop continues with the next iteration right after yield return. Let’s add some debug messages and see what happens:

static IEnumerable<int> Range() {
    Console.WriteLine("hello");
    for (int i = 0; i < 100; i++) {
        yield return i;
        if (i == 6) yield break;
        Console.WriteLine("Last return value: " + i);
    }
    Console.WriteLine("good-bye");
} //

example output:
hello
0
Last return value: 0
1
Last return value: 1
2
Last return value: 2
3
Last return value: 3
4
Last return value: 4
5
Last return value: 5
6

yield break does not leave the for loop. It leaves the method.

There are certain rules for “yield” within try/catch blocks. yield must not be used in finally blocks. yield return can only be used in try blocks. And this only if there is no catch block.

yield cannot appear in anonymous functions.
The use of yield requires iterator blocks.

Using yield can be quite efficient. You do not have to iterate through all elements if the outer loop exits early. This is a nice approach for sequential operations. (((The Parallel class obviously dwarfs yield)))

static IEnumerable<int> Range2() {
    for (int i = 0; i < 100; i++) {
        Thread.Sleep(100);  // long computation of something
        yield return i;
    }
} //

static public void Test2() {
    foreach (int i in Range2()) {
        if (i == 30) break; // remaining results not needed anymore
        Console.WriteLine(i);
    }
} //
Advertisements

About Bastian M.K. Ohta

Happiness only real when shared.

Posted on January 8, 2014, in Advanced, C# and tagged , , , , , , , , , . Bookmark the permalink. Leave a comment.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

w

Connecting to %s

%d bloggers like this: