Possible Duplicate:
C# - Proper Use of yield return
What can be a real use case for C# yield?
Thanks.
Possible Duplicate:
C# - Proper Use of yield return
What can be a real use case for C# yield?
Thanks.
When you want deferred execution.
This makes sense in most cases where the alternative is to construct a temporary collection.
Consider this scenario: I have a list of integers and I want to list their squares.
I could do this:
public static IEnumerable<int> Squares(this IEnumerable<int> numbers) {
List<int> squares = new List<int>();
foreach (int number in numbers)
squares.Add(number * number);
return squares;
}
Then I could sum the squares, take their average, find the greatest, etc.
But I really didn't need to populate a whole new List<int>
for that purpose. I could've used yield
to enumerate over the initial list and return the squares one-by-one:
public static IEnumerable<int> Squares(this IEnumerable<int> numbers) {
foreach (int number in numbers)
yield return number * number;
}
The fact that this actually makes a difference might not be apparent until you start dealing with very large collections, where populating temporary collections proves to be quite wasteful.
For example suppose I wanted to find the first square above a certain threshold. I could do this:
IEnumerable<int> numbers = GetLotsOfNumbers();
var squares = numbers.Squares();
int firstBigSquare = squares
.Where(x => x >= 1000)
.FirstOrDefault();
But if my Squares
method populated an entire List<int>
before returning, the above code would be doing potentially far more work than necessary.
From the MSDN page on yield
:
Used in an iterator block to provide a value to the enumerator object or to signal the end of iteration.
You use it when creating a custom iterator. Using the example from the page:
// yield-example.cs
using System;
using System.Collections;
public class List
{
public static IEnumerable Power(int number, int exponent)
{
int counter = 0;
int result = 1;
while (counter++ < exponent)
{
result = result * number;
yield return result;
}
}
static void Main()
{
// Display powers of 2 up to the exponent 8:
foreach (int i in Power(2, 8))
{
Console.Write("{0} ", i);
}
}
}
The yield
means that the while
loop inside Power
effectively "pauses" after each iteration to allow the calling routine to perform some action. In this case printing out the result.
See this article.
Yield acts as a return-placeholder - it's a non-local goto return point which preserves the method's environment and allows the code to "jump" back in. In a way similar (kind of inverted) to passing a delegate into a method which allows you to inject specific logic within another method, closures allow you to do different types of work "around" a more general method, allowing you to keep code small and modular and re-usable.
This could make for much more efficient code. Instead of instantiating a very large collection, it might be possible to allow individual objects to be acted upon in sequence(and they are discarded after each operation). I imagine you could construct cases where a straightforward iterator would be extremely difficult to build.