.NET Zone is brought to you in partnership with:

I am Microsoft C# MVP July - 2012 My name is Pranay Rana. Currently, I'm working as senior software engineer in a mid-sized company (Ahmedabad). I have 5 years of the experience in web development with Asp.Net, C# and MS SQL server. For me, the definition of programming is: something that you do once and that gets used by multiple users for many years Pranay is a DZone MVB and is not an employee of DZone and has posted 34 posts at DZone. You can read more from them at their website. View Full User Profile

C# State Machine - Yield

08.03.2012
| 3506 views |
  • submit to reddit
The Yield keyword was introduced in C#2.0. Yield allows the creation of a state machine and makes it iterate through the collection of objects one by one.

Yield is a contextual keyword used in iterator methods in C#. See yield being used in the following iterator block.
public IEnumerable methodname(params)
{
      foreach(type element in listofElement)
      {
         ...code for processing
         yield return result;
      }
}
Note : here IEnumerable can be replaced by IEnumerable<T>.

What yield the keyword does: "When you process the collection by this keyword in iterator block. It pause the execution return proceeded  element or the current element of the collection. And when you call it again it start execution with the next element which in turn become current element for that call. This thing get continue till it reach the last element of collection."

Now I am going to show how you can gain some performance when you use yield.
In this example I am checking each datarow of the datatable whether it is empty or not.

Code With Yield Keyword
static void Main(string[] args)
{
     int[] arr = new int[] { 1, 2, 3 };
 
     DataTable table = new DataTable();
     table.Columns.Add("ItemName", typeof(string));
     table.Columns.Add("Quantity", typeof(int));
     table.Columns.Add("Price", typeof(float));
     table.Columns.Add("Process", typeof(string));
     //
     // Here we add five DataRows.
     //
     table.Rows.Add("Indocin", 2, 23);
     table.Rows.Add("Enebrel", 1, 10);
     table.Rows.Add(null, null, null);
     table.Rows.Add("Hydralazine", 1, null);
     table.Rows.Add("Combivent", 3, 5);
     table.Rows.Add("Dilantin", 1, 6);
 
     foreach (DataRow dr in GetRowToProcess(table.Rows))
     {
         if (dr != null)
         {                   
            dr["Process"] = "Processed";
            Console.WriteLine(dr["ItemName"].ToString() 
+ dr["Quantity"].ToString() + " : " + dr["Process"].ToString());
            //bool test = dr.ItemArray.Any(c => c == DBNull.Value);
         }
      }
      Console.ReadLine();
}
private static IEnumerable<datarow>GetRowToProcess(DataRowCollection                                                         dataRowCollection)
{
     foreach (DataRow dr in dataRowCollection)
     {
          bool isempty = dr.ItemArray.All(x => x == null || 
(x!= null && string.IsNullOrWhiteSpace(x.ToString())));
 
          if (!isempty)
          {
             yield return dr;
             //dr["Process"] = "Processed";
          }
          else
          {
             yield return null;
             //dr["Process"] = " Not having data ";
          }
          //yield return dr;
     }
}
Code Without Yield Keyword
private static IList<datarow> GetRowToProcess(DataRowCollection dataRowCollection)
{
    List<datarow> procedeedRows = new List<datarow><datarow>();
    foreach (DataRow dr in dataRowCollection)
    {
        bool isempty = dr.ItemArray.All(x => x == null || </datarow>
<datarow>                           (x!= null && string.IsNullOrWhiteSpace(x.ToString())));
 
        if (!isempty)
        {
          procedeedRows.Add(dr);
        }
     }
     return procedeedRows;
 }
 
static void Main(string[] args)
{
   //code as above function to create datatable
   List<datarow> drs= GetRowToProcess(table.Rows);
   foreach (DataRow dr in drs)
   {
     //code to process the rows
   }
}
</datarow>
Now Difference between two code

Code without yield keyword
In this code there is an extra list that gets created which points to the rows that are matching the condition and then there is a loop for processing each row.

Disadvantage With this code is an extra list that gets created which occupies the extra space i.e memory as well as slowing down the code.

Code with yield keyword
In this snippet there is no extra list that gets created.  The matching conditions get processed one at a time.

Advantage There is no extra list that gets created and also it doesn't cause any performance problem.

Here's an example of LINQ with the yield keyword
void Main()
{
   // This uses a custom 'Pair' extension method, defined below.
   List<string> list1 = new List<string>()
 {
     "Pranay",
     "Rana",
     "Hemang",
     "Vyas"
 };
   IEnumerable<string><string>  query = list1.Select (c => c.ToUpper())
  .Pair()         // Local from this point on.
  .OrderBy (n => n.length);
}
 
public static class MyExtensions
{
 public static IEnumerable<string> Pair (this IEnumerable<string> source)
 {
  string firstHalf = null;
  foreach (string element in source)
  if (firstHalf == null)
   firstHalf = element;
  else
  {
   yield return firstHalf + ", " + element;
   firstHalf = null;
  }
 }
}
</string>
There is another statement besides yield return

yield break

This stops returning sequence elements (this happens automatically if control reaches the end of the iterator method body).

The iterator code uses the yield return statement to return each element in turn. A yield break ends the iteration.

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

  • Unsafe blocks are not allowed.
  • Parameters to the method, operator, or accessor cannot be ref or out.
  • A yield statement cannot appear in an anonymous method.
  • 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.



Published at DZone with permission of Pranay Rana, author and DZone MVB. (source)

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)

Tags: