What does the yield keyword do there? I've seen it referenced in a couple places, and one other question, but I haven't quite figured out what it actually does. I'm used to thinking of yield in the sense of one thread yielding to another, but that doesn't seem relevant here.

16 Answers
16

The yield keyword actually does quite a lot here. The function returns an object that implements the IEnumerable interface. If a calling function starts foreach-ing over this object the function is called again until it "yields". This is syntactic sugar introduced in C# 2.0. In earlier versions you had to create your own IEnumerable and IEnumerator objects to do stuff like this.

The easiest way understand code like this is to type in an example, set some breakpoints and see what happens.

In this case that would be easier, i'm just using the integer here to show how yield return works. The nice things about using yield return is that it's a very quick way of implementing the iterator pattern, so things are evaluated lazly.
– MendeltDec 22 '08 at 8:35

99

Also worth noting you can use yield break; when you don't want to return any more items.
– RoryMay 17 '11 at 18:13

yield is not a keyword. If it were then I could not use yield as an identifier as in int yield = 500;
– BrandinFeb 19 '15 at 19:15

6

'If a calling function starts foreach-ing over this object the function is called again until it "yields"'. doesn't sound right to me. I always thought of the c# yield keyword in the context of "the crop yields a bountiful harvest", instead of "the car yields to the pedestrian".
– ZackMay 31 '16 at 15:28

While it's nominally used for easily implementing an iterator pattern, but can be generalized into a state machine. No point in quoting Raymond, the last part also links to other uses (but the example in Entin's blog is esp good, showing how to write async safe code).

yield return is used with enumerators. On each call of yield statement, control is returned to the caller but it ensures that the callee's state is maintained. Due to this, when the caller enumerates the next element, it continues execution in the callee method from statement immediately after the yield statement.

Let us try to understand this with an example. In this example, corresponding to each line I have mentioned the order in which execution flows.

Intuitively, the keyword returns a value from the function without leaving it, i.e. in your code example it returns the current item value and then resumes the loop. More formally, it is used by the compiler to generate code for an iterator. Iterators are functions that return IEnumerable objects. The MSDN has several articles about them.

A list or array implementation loads all of the items immediately whereas the yield implementation provides a deferred execution solution.

In practice, it is often desirable to perform the minimum amount of work as needed in order to reduce the resource consumption of an application.

For example, we may have an application that process millions of records from a database. The following benefits can be achieved when we use IEnumerable in a deferred execution pull-based model:

Scalability, reliability and predictability are likely to improve since the number of records does not significantly affect the application’s resource requirements.

Performance and responsiveness are likely to improve since processing can start immediately instead of waiting for the entire collection to be loaded first.

Recoverability and utilisation are likely to improve since the application can be stopped, started, interrupted or fail. Only the items in progress will be lost compared to pre-fetching all of the data where only using a portion of the results was actually used.

Continuous processing is possible in environments where constant workload streams are added.

Here is a comparison between build a collection first such as a list compared to using yield.

Here is a simple way to understand the concept:
The basic idea is, if you want a collection that you can use "foreach" on, but gathering the items into the collection is expensive for some reason (like querying them out of a database), AND you will often not need the entire collection, then you create a function that builds the collection one item at a time and yields it back to the consumer (who can then terminate the collection effort early).

Think of it this way: You go to the meat counter and want to buy a pound of sliced ham. The butcher takes a 10-pound ham to the back, puts it on the slicer machine, slices the whole thing, then brings the pile of slices back to you and measures out a pound of it. (OLD way).
With yield, the butcher brings the slicer machine to the counter, and starts slicing and "yielding" each slice onto the scale until it measures 1-pound, then wraps it for you and you're done. The Old Way may be better for the butcher (lets him organize his machinery the way he likes), but the New Way is clearly more efficient in most cases for the consumer.

The yield keyword allows you to create an IEnumerable<T> in the form on an iterator block. This iterator block supports deferred executing and if you are not familiar with the concept it may appear almost magical. However, at the end of the day it is just code that executes without any weird tricks.

An iterator block can be described as syntactic sugar where the compiler generates a state machine that keeps track of how far the enumeration of the enumerable has progressed. To enumerate an enumerable, you often use a foreach loop. However, a foreach loop is also syntactic sugar. So you are two abstractions removed from the real code which is why it initially might be hard to understand how it all works together.

In an attempt to untangle this I have crated a sequence diagram with the abstractions removed:

The state machine generated by the compiler also implements the enumerator but to make the diagram more clear I have shown them as separate instances. (When the state machine is enumerated from another thread you do actually get separate instances but that detail is not important here.)

Every time you call your iterator block a new instance of the state machine is created. However, none of your code in the iterator block is executed until enumerator.MoveNext() executes for the first time. This is how deferred executing works. Here is a (rather silly) example:

var evenNumbers = IteratorBlock().Where(i => i%2 == 0);

At this point the iterator has not executed. The Where clause creates a new IEnumerable<T> that wraps the IEnumerable<T> returned by IteratorBlock but this enumerable has yet to be enumerated. This happens when you execute a foreach loop:

If you enumerate the enumerable twice then a new instance of the state machine is created each time and your iterator block will execute the same code twice.

Notice that LINQ methods like ToList(), ToArray(), First(), Count() etc. will use a foreach loop to enumerate the enumerable. For instance ToList() will enumerate all elements of the enumerable and store them in a list. You can now access the list to get all elements of the enumerable without the iterator block executing again. There is a trade-off between using CPU to produce the elements of the enumerable multiple times and memory to store the elements of the enumeration to access them multiple times when using methods like ToList().

The C# yield keyword, to put it simply, allows many calls to a body of code, referred to as an iterator, that knows how to return before it's done and, when called again, continues where it left off - i.e. it helps an iterator become transparently stateful per each item in a sequence that the iterator returns in successive calls.

It is a very simple and easy way to create an enumerable for your object. The compiler creates a class that wraps your method and that implements, in this case, IEnumerable<object>. Without the yield keyword, you'd have to create an object that implements IEnumerable<object>.

Notice that yield return won't return from the method. You can even put a WriteLine after the yield return

The above produces an IEnumerable of 4 ints 4,4,4,4

Here with a WriteLine. Will add 4 to the list, print abc, then add 4 to the list, then complete the method and so really return from the method(once the method has completed, as would happen with a procedure without a return). But this would have a value, an IEnumerable list of ints, that it returns on completion.

Notice also that when you use yield, what you are returning is not of the same type as the function. It's of the type of an element within the IEnumerable list.

You use yield with the method's return type as IEnumerable. If the method's return type is int or List<int> and you use yield, then it won't compile. You can use IEnumerable method return type without yield but it seems maybe you can't use yield without IEnumerable method return type.

note- if trying to understand SelectMany, it uses yield and also generics.. this example may help public static IEnumerable<TResult> testYieldc<TResult>(TResult t) { yield return t; } and public static IEnumerable<TResult> testYieldc<TResult>(TResult t) { return new List<TResult>(); }
– barlopMay 1 '16 at 2:16

Looks like very good explanation ! This could have been the accepted answer.
– pongapunditJul 11 '18 at 15:37

@pongapundit thanks, my answer is certainly clear and simple, but I haven't used yield much myself, other answerers have much more experience with it and knowledge of its uses than I do. What I wrote of yield here was probably from scratching my head trying to figure out some of the answers here and at that dotnetperls link! But since I don't know yield return that well (other than the simple thing I mentioned), and haven't used it much and don't know much re its uses, I don't think this should be the accepted one.
– barlopJul 12 '18 at 13:09

The Array's each method implementation yields control over to the caller (the 'puts x') with each element of the array neatly presented as x. The caller can then do whatever it needs to do with x.

However .Net doesn't go all the way here.. C# seems to have coupled yield with IEnumerable, in a way forcing you to write a foreach loop in the caller as seen in Mendelt's response. Little less elegant.

-1 This answer does not sound right to me. Yes, C# yield is coupled with IEnumerable, and C# lacks the Ruby concept of a "block". But C# has lambdas, which could allow the implementation of a ForEach method, much alike Ruby's each. This that does not mean it would be a good idea to do so, though.
– rsennaMay 15 '13 at 19:27

Thank you for your interest in this question.
Because it has attracted low-quality or spam answers that had to be removed, posting an answer now requires 10 reputation on this site (the association bonus does not count).