tags:

views:

634

answers:

7

I know what yield does, and I've seen a few examples, but I can't think of real life applications, have you used it to solve some specific problem?

(Ideally some problem that cannot be solved some other way)

+4  A: 

actually I use it in a non traditional way on my site IdeaPipe

public override IEnumerator<T> GetEnumerator()
{
 // goes through the collection and only returns the ones that are visible for the current user
 // this is done at this level instead of the display level so that ideas do not bleed through
 // on services
 foreach (T idea in InternalCollection)
  if (idea.IsViewingAuthorized)
   yield return idea;
}

so basically it checks if viewing the idea is currently authorized and if it is it returns the idea. If it isn't, it is just skipped. This allows me to cache the Ideas but still display the ideas to the users that are authorized. Else I would have to re pull them each time based on permissions, when they are only re-ranked every 1 hour.

Nick Berardi
+1  A: 

LINQ's operators on the Enumerable class are implemented as iterators that are created with the yield statement. It allows you to chain operations like Select() and Where() without actually enumerating anything until you actually use the enumerator in a loop, typically by using the foreach statement. Also, since only one value is computed when you call IEnumerator.MoveNext() if you decide to stop mid-collection, you'll save the performance hit of calculating all of the results.

Iterators can also be used to implement other kinds of lazy evaluation where expressions are evaluated only when you need it. You can also use yield for more fancy stuff like coroutines.

Mark Cidade
A: 

Another good use for yield is to perform a function on the elements of an IEnumerable and to return a result of a different type, for example:

public delegate T SomeDelegate(K obj);

public IEnumerable<T> DoActionOnList(IEnumerable<K> list, SomeDelegate action)
{
    foreach (var i in list)
        yield return action(i);
}
Jon Limjap
+2  A: 

One interesting use is as a mechanism for asynchronous programming esp for tasks that take multiple steps and require the same set of data in each step. Two examples of this would be Jeffery Richters AysncEnumerator Part 1 and Part 2. The Concurrency and Coordination Runtime (CCR) also makes use of this technique CCR Iterators.

dpp
A: 

@Jon You mean like LINQ's map operator?

IEnumerable<TResult> Select<TSource,TResult>
                       (this IEnumerable<TSource>  source, 
                             Func<TSource,TResult> selector)
 { foreach(TSource element in source) yield return selector(element);
 }
Mark Cidade
+1  A: 

Using yield can prevent downcasting to a concrete type. This is handy to ensure that the consumer of the collection doesn't manipulate it.

Scott Muc
+2  A: 

I realise this is an old question (pre Jon Skeet?) but I have been considering this question myself just lately. Unfortunately the current answers here (in my opinion) don't mention the most obvious advantage of the yield statement.

The biggest benefit of the yield statement is that it allows you to iterate over very large lists with much more efficient memory usage then using say a standard list.

For example, let's say you have a database query that returns 1 million rows. You could retrieve all rows using a DataReader and store them in a List, therefore requiring list_size * row_size bytes of memory.

Or you could use the yield statement to create an Iterator and only ever store one row in memory at a time. In effect this gives you the ability to provide a "streaming" capability over large sets of data.

Moreover, in the code that uses the Iterator, you use a simple foreach loop and can decide to break out from the loop as required. If you do break early, you have not forced the retrieval of the entire set of data when you only needed the first 5 rows (for example).

Regarding:

Ideally some problem that cannot be solved some other way

The yield statement does not give you anything you could not do using your own custom iterator implementation, but it saves you needing to write the often complex code needed. There are very few problems (if any) that can't solved more than one way.

Here are a couple of more recent questions and answers that provide more detail:

http://stackoverflow.com/questions/384392/yield-keyword-value-added

http://stackoverflow.com/questions/317619/is-yield-useful-outside-of-linq

Ash