Introduction
The yield
keyword introduced in C# 2.0. The yield
keyword allows you to create a state machine iterate through the collection of objects one by one.
Yield
is a contextual keyword used in iterator methods in C#. Yield
use like following in iterator block
public IEnumerable methodname(params)
{
foreach(type element in listofElement)
{
...code for processing
yield return result;
}
}
Note: Here IEnumerable
can be replace by IEnumerable<T>
.
So actually the yield
keyword does is "When you process the collection by this keyword in iterator block. It pauses the execution and returns the proceeded element or the current element of the collection. And when you call it again it starts the execution with the next element which in turn becomes the current element for that call. This continues until it reachs the last element of the collection."
Now I am going to show how you how you can gain some performance when you make use of yield
keyword.
In this example I am checking each datarow
of the datatable
weather 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));
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());
}
}
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;
}
else
{
yield return null;
}
}
}
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 || (x!= null && string.IsNullOrWhiteSpace(x.ToString())));
if (!isempty)
{
procedeedRows.Add(dr);
}
}
return procedeedRows;}
static void Main(string[] args)
{
List<datarow> drs= GetRowToProcess(table.Rows);
foreach (DataRow dr in drs)
{
}
}
</datarow>
Now Difference Between Two Code
In Code (Code Without Yield Keyword)
In this code there is an extra list which gets created that points to the rows that match the condition. Then there is a loop for processing each row.
Disadvantage within this code is an extra list which gets created and occupies the extra space (i.e. occupies memory as well as slows down the code).
In Code (Code With Yield Keyword)
In this no extra list is getting created, with help yield one row at a time with a matching condition is getting processed.
The advantage of the code is that there is no extra list getting created and also it also doesn't cause any performance problems.
The following is an example of LINQ with the yield
keyword
void Main()
{
List<string> list1 = new List<string>()
{
"Pranay",
"Rana",
"Hemang",
"Vyas"
};
IEnumerable<string><string> query = list1.Select (c => c.ToUpper())
.Pair() .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 other statement besides yeild
return
yield break
stops returning sequence elements (this happens automatically if the control reaches the end of the iterator method body). The iterator code uses the yield return statement to return each element in turn. 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.