The yield keyword uses what's known as lazy evaluation. What this means practically is that anything following a "yield return" will not be evaluated until it is requested from the enumerator. Take the following class for example:
public class ExampleClass{
public List<string> OriginalStrings { get; set; }
/// <summary>
/// Returns an enumerated list of reversed strings from OriginalStrings.
/// Causes side effects due to the call to "reverseString".
/// </summary>
/// <returns></returns>
public IEnumerable<string> GetReversedStrings()
{
for (int i = 0; i < OriginalStrings.Count; i++)
yield return reverseString(i);
}
/// <summary>
/// Replaces the string at the specified index with a reversed version of itself.
/// </summary>
/// <param name="index">The index of the string in OriginalStrings to reverse. </param>
/// <returns>The newly reversed string</returns>
private string reverseString(int index)
{
string value = OriginalStrings[index];
char[] chars = value.ToCharArray();
Array.Reverse(chars);
string[] letters = new string[chars.Length];
for (int i = 0; i < chars.Length; i++)
letters[i] = chars[i].ToString();
string returnValue = string.Join("", letters);
OriginalStrings[index] = returnValue;
return OriginalStrings[index];
}
}
The GetReversedStrings method will yield the result of the call to reverseString, which will set the values of the OriginalStrings to their reversed equivalent, and return the newly reversed string.
Now, let's call this from the main method:
static void Main(string[] args)
{
ExampleClass exampleClass = new ExampleClass();
exampleClass.OriginalStrings = new List<string>() { "Bob", "David", "Jimenez", "Franz" };
exampleClass.GetReversedStrings();
foreach (string s in exampleClass.OriginalStrings)
Console.WriteLine(s);
Console.ReadLine();
}
Notice the output. The strings are not reversed. This is because the result of GetReversedStrings() is never iterated through.
Let's alter the code just a bit.
static void Main(string[] args)
{
ExampleClass exampleClass = new ExampleClass();
exampleClass.OriginalStrings = new List<string>() { "Bob", "David", "Jimenez", "Franz" };
foreach (string value in exampleClass.GetReversedStrings())
{
// do nothing of consequence. This is here simply to iterate through the values.
}
foreach (string s in exampleClass.OriginalStrings)
Console.WriteLine(s);
Console.ReadLine();
}
Now, you'll see a different result when you run this. All of the values will print out reversed. This is because the call to the statement returned in the yield return statement is evaluated only when iterated through.
This can certainly be an advantage, as it is in Linq, but use the keyword improperly, and you might get unexpected results.