Problem
One of the responses to the How Can I Expose Only a Fragment of IList> question included the following code snippet:
IEnumerable<object> FilteredList()
{
foreach(object item in FullList)
{
if(IsItemInPartialList(item))
yield return item;
}
}
What is the purpose of the yield keyword in this case? I’ve seen it mentioned in a few places even in response to another inquiry, but I’m still not sure what it accomplishes. I’m used to thinking of yield as one thread giving way to another, but that doesn’t seem to be the case here.
Asked by Herms
Solution #1
The yield contextual keyword helps a lot in this case.
The function returns an IEnumerable object that implements the IEnumerable interface. If a calling function begins foreaching over this object, it is called again until the object “yields.” This is a new syntactic sugar in C# 2.0. To accomplish things like this in previous versions, you had to develop your own IEnumerable and IEnumerator objects.
To comprehend code like this, type in an example, create some breakpoints, and see what happens. Take a look at the following scenario:
public void Consumer()
{
foreach(int i in Integers())
{
Console.WriteLine(i.ToString());
}
}
public IEnumerable<int> Integers()
{
yield return 1;
yield return 2;
yield return 4;
yield return 8;
yield return 16;
yield return 16777216;
}
When you run the sample, you’ll notice that the first Integers() call returns 1. The second call returns 2, and the yield return 1 line is not repeated.
Here’s an example from actual life:
public IEnumerable<T> Read<T>(string sql, Func<IDataReader, T> make, params object[] parms)
{
using (var connection = CreateConnection())
{
using (var command = CreateCommand(CommandType.Text, sql, connection, parms))
{
command.CommandTimeout = dataBaseSettings.ReadCommandTimeout;
using (var reader = command.ExecuteReader())
{
while (reader.Read())
{
yield return make(reader);
}
}
}
}
}
Answered by Mendelt
Solution #2
Iteration. It generates a “under the hood” state machine that remembers where you were on each subsequent cycle of the function and continues from there.
Answered by Joel Coehoorn
Solution #3
Yield has two major applications.
I developed a simple video to demonstrate the above two concepts more clearly. You can watch it here.
Answered by Shivprasad Koirala
Solution #4
Raymond Chen recently published a series of papers on the yield keyword.
While it’s intended to be used for quickly building an iterator pattern, it may also be used to create a state machine. There’s no point in repeating Raymond because the last portion also connects to other uses (though Entin’s blog example is particularly useful for explaining how to construct async safe code).
Answered by Svend
Solution #5
At first glance, give return appears to be a.NET shortcut for returning an IEnumerable.
Without yield, all of the collection’s elements are created at the same time:
class SomeData
{
public SomeData() { }
static public IEnumerable<SomeData> CreateSomeDatas()
{
return new List<SomeData> {
new SomeData(),
new SomeData(),
new SomeData()
};
}
}
Using yield, the following code returns items one by one:
class SomeData
{
public SomeData() { }
static public IEnumerable<SomeData> CreateSomeDatas()
{
yield return new SomeData();
yield return new SomeData();
yield return new SomeData();
}
}
The benefit of yield is that if the function that consumes your data only need the first item in the collection, the remaining items will not be created.
The yield operator allows items to be created as they are needed. That’s a compelling argument to employ it.
Answered by Marquinho Peli
Post is based on https://stackoverflow.com/questions/39476/what-is-the-yield-keyword-used-for-in-c