The Yield Statement

Yield , one of the most powerfull, most ignored feature by developers.I was one of them until I used it. First ,yield is not an operator. yield return and yield break are statements.

In C#, when we are returning an IEnumerable collection from a method, we are allowed to use the yield keyword to transform method into an “iterator block”.

As per MSDN

The yield keyword signals to the compiler that the method in which it appears is an iterator block.  The compiler generates a class to implement the behavior that is expressed in the iterator block.  In the iterator block, the yield keyword is used together with the return keyword to provide a value to the enumerator object.  This is the value that is returned, for example, in each loop of a foreach statement.  The yield keyword is also used with break to signal the end of iteration.

In other words
The yield keyword is used in an iterator block to provide value of enumerator object or to signal the end of the iteration.

yield keyword can be used as:

1)yield return <expression>;
2)yield break;

When used as the expression is evaluated and returned as a value to the enumerator object.Also the expression has to be implicitebly convertible to yield type of the iterator.

When used as break,Yield break control is unconditionally returned to the caller of the iterator in two cases.
One as specified above is MoveNext method of iterator &  Other can be dispose method of enumerator (iterator) object.

public class Program
{
public static IEnumerable GetEvenNumbers(int[] numbers)
{
foreach (int item in numbers)
{
if (item % 2 == 0)
yield return (item);
}
}
public static IEnumerableGetFirstEvenNumber(int[] numbers)
{
foreach (int item in numbers)
{
if (item % 2 == 0)
{
yield return (item);
yield break;
}
}
//This Loop , will not get called.
foreach (int item in numbers)
{
if (item % 2 == 1)
yield return item;}
}


public static void Main()
{
int[] numbers = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 };


// Yield Return  – Example Call Start
var evenNumbersCol = GetEvenNumbers(numbers);
foreach (int x in evenNumbersCol)
{
Console.WriteLine(x);
}
// Yield Return  – Example Call End


// Yield Break – Example Call Start
var firstEvenNumber = GetFirstEvenNumber(numbers);
foreach (int x in firstEvenNumber)
{
Console.WriteLine(“First Even Number = ” + x.ToString());
}
// Yield Break – Example Call End
Console.ReadLine();
}

In the Program sample above , I mentioned the example call for both Yield Return & Yield Break

The program will return Even numbers.
The Collection evenNumbersCol/firstEvenNumber is empty before it is been accessed in foreach.The methods are getting called actuallly when any of iterator methods getting called or when looped through in other words when used to return items from a loop within a method ( return type IEnumerable) and retain the state of the method through multiple calls.This saves the memory by preventing fully populating large collection of items

Yield Return:
When used as the expression is evaluated and returned as a value to the enumerator object.”The expression has to be implicitebly convertible to yield type of the iterator.” means return type of yield must match to IEnumerable, in our above case int

Yield Break:
When used as break,Yield break control is unconditionally returned to the caller of the iterator in two cases. One as specified above is Move next method of iterator ( i.e. Looping through as we discussed above) &  Other can be dispose method of enumerator (iterator) object.Also yield break can be seen as return statement which does not return value.
If you are inside this loop want to abort the iteration and return as soon as first even number found , you can do this with help of the yield break. The yield break will return from the method directly instead of the current loop in other words second loop will never get executed here

As per MSDN Yield have following restrictions

The yield statement can only appear inside an iterator block, which can be implemented as the body of a method, operator, or accessor. The body of such methods, operators, or accessors is controlled by the following restrictions:


1) Unsafe blocks are not allowed.
2) Parameters to the method, operator, or accessor cannot be ref or out.
3) A yield return statement cannot be located anywhere inside a try-catch block.
It can be located in a try block if the try block is followed by a finally block.
4) A yield break statement may be located in a try block or a catch block but not a finally block.
5) A yield statement cannot appear in an anonymous method.
6) When used with expression, a yield return statement cannot appear in a catch block or in a try block that has one or more catch clauses.

Advertisements

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 )

Twitter picture

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

Facebook photo

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

Google+ photo

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

Connecting to %s