Yield Statement in C# (Useful LINQ statement)

Many times we need to collect a number of results depending upon certain conditions. And for that we need to create some sort of collection objects, inserting the output to that collection and then returing that collection at last. But it is very cumbersome to do that.

Rather a simple way to do that is to use Yield statement (C# 2,0 onwards). This keyword is used to return items from a loop within a method and retain the state of the method through multiple calls.

Yield returns IEnumerator or generic IEnumerator<T>.

public static IEnumerator<int> GetCounter()
{
      for (int count = 0; count < 10; count++)
      {
          yield return count;
      }
}
This will return the collection IEnumerator<int> which can be used to
get the objects returned. 
IEnumerator<int> list =  GetCounter();
Console.Write(list.MoveNext() + " "+ list.Current);

There is also the yield break statement. If a yield break statement
is hit within a method,execution of that method stops
with no return.Using this, the first method could be
rewritten like this;

public static IEnumerator<int> GetCounter()
{
   int max = 10, min = 5;
   while (true)
   {
      if (min >= max)
      {
         yield break;
      }
      yield return min++;
   }
}
Before I go any further, it's worth remembering that an iterator block
doesn't just run from start to finish.  When the method is originally
called, the iterator is just created. It's only when MoveNext() is called.
At that point, execution starts at the top of the method as normal,
and progresses as far as the first yield return or yield break statement,
or the end of the method. At that point, a Boolean value is returned to
indicate whether or not the block has finished iterating.
If/when MoveNext()  is called again, the method continues executing from
just after the yield return statement.
Means in each & every MoveNext() function, Iteration Funtion would be 
called and will execute the statement starting from the last  yield to 
the next yield statement.
using System;
using System.Collections.Generic; 
class Test
{
    static readonly string Padding = new string(' ', 30);
    static IEnumerator<int> GetNumbers()
    {

        Console.WriteLine(“First line of GetNumbers()”);

        Console.WriteLine(“Just before yield return 0”);

        yield return 10;

        Console.WriteLine(“Just after yield return 0”);

 

        Console.WriteLine(“Just before yield return 1”);

        yield return 20;

        Console.WriteLine("Just after yield return 1");
    }    
    static void Main()
    {

           Console.WriteLine(“Calling GetNumbers()”);

           IEnumerator<int> iterator = GetNumbers();

           Console.WriteLine(“Calling MoveNext()…”);

           bool more = iterator.MoveNext();

Console.WriteLine(“Result={0}; Current={1}”, more, iterator.Current);

 

           Console.WriteLine(“Calling MoveNext() again…”);

           more = iterator.MoveNext();

Console.WriteLine(“Result={0}; Current={1}”, more, iterator.Current);

 

           Console.WriteLine(“Calling MoveNext() again…”);

           more = iterator.MoveNext();

           Console.WriteLine("Result={0} (stopping)", more);
    }
} 
-----Result 
Calling GetNumbers()
Calling MoveNext()...
                              First line of GetNumbers()
                              Just before yield return 0
Result=True; Current=10
Calling MoveNext() again...
                              Just after yield return 0
                              Just before yield return 1
Result=True; Current=20
Calling MoveNext() again...
                              Just after yield return 1
Result=False (stopping) 
Reference: http://csharpindepth.com/Articles/Chapter6/IteratorBlockImplementation.aspx

This is very useful in LINQ query expressions in C# 3.0 as this provides the iterations required in LINQ queries.

Suppose there is CustomerCollection Class having customers list (IEnumerable<Customer> _customers)

public class CustomerCollection : IEnumerable<Customer>

This class is being used in LINQ query to iterate through the customer object contained in its list (_customers) and thus is supposed to implement GetEnumerator method as:

public IEnumerator<Customer> GetEnumerator()

{

foreach (Customer customer in _customers)

yield return customer;   

}

Advertisements
This entry was posted in .Net 2.0 and tagged . Bookmark the permalink.

2 Responses to Yield Statement in C# (Useful LINQ statement)

  1. Joy says:

    Great feature..! Hopefully I’ll be able to work on it further.
    thanks.

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