Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the purpose/advantage of using yield return iterators in C#?

All of the examples I've seen of using yield return x; inside a C# method could be done in the same way by just returning the whole list. In those cases, is there any benefit or advantage in using the yield return syntax vs. returning the list?

Also, in what types of scenarios would yield return be used that you couldn't just return the complete list?

like image 247
CoderDennis Avatar asked Jul 06 '09 18:07

CoderDennis


People also ask

When should you use yield return?

You use a yield return statement to return each element one at a time. The sequence returned from an iterator method can be consumed by using a foreach statement or LINQ query. Each iteration of the foreach loop calls the iterator method.

What is the benefit of yield C#?

The advantage of using yield is that if the function consuming your data simply needs the first item of the collection, the rest of the items won't be created so it's more efficient. The yield operator allows the creation of items as it is demanded. That's a good reason to use it.

What should the return type be for a method that uses yield return?

The yield return statement returns one element at a time. The return type of yield keyword is either IEnumerable or IEnumerator . The yield break statement is used to end the iteration. We can consume the iterator method that contains a yield return statement either by using foreach loop or LINQ query.

What is the use of the yield keyword?

Yield is a keyword in Python that is used to return from a function without destroying the states of its local variable and when the function is called, the execution starts from the last yield statement. Any function that contains a yield keyword is termed a generator. Hence, yield is what makes a generator.


2 Answers

But what if you were building a collection yourself?

In general, iterators can be used to lazily generate a sequence of objects. For example Enumerable.Range method does not have any kind of collection internally. It just generates the next number on demand. There are many uses to this lazy sequence generation using a state machine. Most of them are covered under functional programming concepts.

In my opinion, if you are looking at iterators just as a way to enumerate through a collection (it's just one of the simplest use cases), you're going the wrong way. As I said, iterators are means for returning sequences. The sequence might even be infinite. There would be no way to return a list with infinite length and use the first 100 items. It has to be lazy sometimes. Returning a collection is considerably different from returning a collection generator (which is what an iterator is). It's comparing apples to oranges.

Hypothetical example:

static IEnumerable<int> GetPrimeNumbers() {    for (int num = 2; ; ++num)         if (IsPrime(num))            yield return num; }  static void Main() {     foreach (var i in GetPrimeNumbers())         if (i < 10000)            Console.WriteLine(i);        else            break; } 

This example prints prime numbers less than 10000. You can easily change it to print numbers less than a million without touching the prime number generation algorithm at all. In this example, you can't return a list of all prime numbers because the sequence is infinite and the consumer doesn't even know how many items it wants from the start.

like image 173
mmx Avatar answered Sep 17 '22 13:09

mmx


The fine answers here suggest that a benefit of yield return is that you don't need to create a list; Lists can be expensive. (Also, after a while, you'll find them bulky and inelegant.)

But what if you don't have a List?

yield return allows you to traverse data structures (not necessarily Lists) in a number of ways. For example, if your object is a Tree, you can traverse the nodes in pre- or post- order without creating other lists or changing the underlying data structure.

public IEnumerable<T> InOrder() {     foreach (T k in kids)         foreach (T n in k.InOrder())             yield return n;     yield return (T) this; }  public IEnumerable<T> PreOrder() {     yield return (T) this;     foreach (T k in kids)         foreach (T n in k.PreOrder())             yield return n; } 
like image 29
Ray Avatar answered Sep 21 '22 13:09

Ray