Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

After almost 4 years of experience, I haven't seen a code where yield keyword is used. Can somebody show me a practical usage (along explanation) of this keyword, and if so, aren't there other ways easier to fullfill what it can do?

share|improve this question
6  
All (or at least most) of LINQ is implemented using yield. Also Unity3D framework has found some good use for it - it is used to pause functions (on yield statements) and resume it later using the state in the IEnumerable. –  Dani Jul 30 '11 at 18:34
1  
Shouldn't this be moved to StackOverflow? –  Danny Varod Jul 31 '11 at 12:29
2  
@Danny - It's not suitable for Stack Overflow, as the question isn't asking to solve a specific problem but asking about what yield can be used for in general. –  ChrisF Jul 31 '11 at 13:05
6  
For real? I can't think of a single app where I haven't used it. –  Aaronaught Jul 31 '11 at 15:48

5 Answers 5

up vote 44 down vote accepted

Efficiency

The yield keyword effectively creates a lazy enumeration over collection items that can be much more efficient. For example, if your foreach loop iterates over just the first 5 items of 1 million items then that's all yield returns, and you didn't build up a collection of 1 million items internally first. Likewise you will want to use yield with IEnumerable<T> return values in your own programming scenarios to achieve the same efficiencies.

Example of efficiency gained in a certain scenario

Not an iterator method, potential inefficient use of a big collection,
(Intermediate collection is built having lots of items)

// Method returns all million items before anything can loop over them. 
List<object> GetAllItems() {
    List<object> millionCustomers;
    database.LoadMillionCustomerRecords(millionCustomers); 
    return millionCustomers;
}

// MAIN example ---------------------
// Caller code sample:
int num = 0;
foreach(var itm in GetAllItems())  {
    num++;
    if (num == 5)
        break;
}
// Note: One million items returned, but only 5 used. 

Iterator version, efficient
(No intermediate collection is built)

// Yields items one at a time as the caller's foreach loop requests them
IEnumerable<object> IterateOverItems() {
    for (int i; i < database.Customers.Count(); ++i)
        yield return database.Customers[i];
}

// MAIN example ---------------------
// Caller code sample:
int num = 0;
foreach(var itm in IterateOverItems())  {
    num++;
    if (num == 5)
        break;
}
// Note: Only 5 items were yielded and used out of the million.

Simplify some programming scenarios

In another case, it makes some kinds of sorting and merging of lists easier to program because you just yield items back in the desired order rather than sorting them into an intermediate collection and swapping them in there. There are many such scenarios.

Just one example is the merging of two lists:

IEnumerable<object> EfficientMerge(List<object> list1, List<object> list2) {
    foreach(var o in list1) 
        yield return o; 
    foreach(var o in list2) 
        yield return o;
}

This method yields back one contiguous list of items, effectively a merge with no intermediate collection needed.

More Info

The yield keyword can only be used in context of an iterator method (having a return type of IEnumerable, IEnumerator, IEnumerable<T>, or IEnumerator<T>.) and there is a special relationship with foreach. Iterators are special methods. The MSDN yield documentation and iterator documentation contains lots of interesting information and explanation of the concepts. Be sure to correlate it with the foreach keyword by reading about it too, to supplement your understanding of iterators.

To learn about how the iterators achieve their efficiency, the secret is in the IL code generated by the C# compiler. The IL generated for an iterator method differs drastically from that generated for a regular (non-iterator) method. This article (What Does the Yield Keyword Really Generate?) provides that kind of insight.

share|improve this answer
    
They're particularly useful for algorithms that take a (possibly long) sequence and generate another one where the mapping is not one-to-one. An example of this is polygon clipping; any particular edge may generate many or even no edges once clipped. Iterators make this enormously easier to express, and yielding is one of the best ways to write them. –  Donal Fellows Jul 31 '11 at 11:25
    
+1 Much better answer as I had written down. Now I also learned yield is good for better performance. –  Jan_V Jul 31 '11 at 12:27
    
Once upon a time, I used yield to build packets for a binary network protocol. It seemed the most natural choice in C#. –  György Andrasek Jul 31 '11 at 16:19
1  
+1 for merge, I really liked(I'm a Java guy) –  Silviu Burcea Jun 27 at 9:38

One of the usages for yield is when you want to return a collection from a method. Instead of writing something like this:

private IEnumerable<int> DoSomething(IEnumerable<int> somePrefilledCollectionWithOtherStuffInIt)
{
    var collection = new List<int>();
    foreach (var i in somePrefilledCollectionWithOtherStuffInIt)
    {
        collection.Add(i);
    }
    return collection;
}

You can now make it smaller like:

private IEnumerable<int> DoSomething(IEnumerable<int> somePrefilledCollectionWithOtherStuffInIt)
{
    foreach (var i in somePrefilledCollectionWithOtherStuffInIt)
    {
        yield return i;
    }
}

This saves you the hassle of making some silly collection variable. Ofcourse this example isn't a reallife scenario.

When doing a search in the Orchard CMS source I stumbled across a nice real life example:

IEnumerable<ShellSettings> LoadSettings() {
    var filePaths = _appDataFolder
        .ListDirectories("Sites")
        .SelectMany(path => _appDataFolder.ListFiles(path))
        .Where(path => string.Equals(Path.GetFileName(path), "Settings.txt", StringComparison.OrdinalIgnoreCase));

    foreach (var filePath in filePaths) {
        yield return ParseSettings(_appDataFolder.ReadFile(filePath));
    }
}

This is the most practical use I've used it for. I've used it myself a couple of times, but that's on my work machine and isn't booted up right now, so can't show you an example of myself.

It's a usefull keyword if you want to have cleaner/shorter code, but you can perfectly live without it.

share|improve this answer
3  
Also note that the yield keyword effectively creates a "lazy load" situation (I used that term loosely) over the collection items that can be much more efficient. For example, if your foreach loop iterates over the first 5 items of 1 million then that's all the yield returns, and you didn't build up a collection of 1 million items internally first. Likewise you will want to use yield with IEnumerable<T> return values in situations to achieve the same efficiencies. –  John K Jul 30 '11 at 18:35
    
In another case, it makes some kinds of sorting and merging of lists easier to program because you just yield items back in the desired order rather than sorting them into an intermediate collection and swapping them, to achieve an ordered collection. There are many scenarios. Just one is the merging of two lists: foreach(var o in list1) yield return o; foreach(var o in list2) yield return o;. The IEnumerable<object> method that contains this code will yield back one contiguous list of items, it's effectively a merge with no intermediate collection created inside the method. –  John K Jul 30 '11 at 18:41
1  
@John K, it's a pity that you haven't posted your both comments as an answer, since it is the answer to the question. If yield exists, it is because it allows lazy enumerations, not because it shortens the code. Actually, the answer by Jan_V is false, and the answer by Jalayn is incomplete. –  MainMa Jul 30 '11 at 19:38
    
@MainMa, I threw my information into an answer because it's likely to get more exposure and to be more easily learned from there (better formatting to work with). Thanks for the suggestion. –  John K Jul 31 '11 at 4:37
    
I used this approach in developing unit tests, where I wanted to pass a collection of data into a test one by one. The collection represented different variations of a "normal" object that should all result in the same outcome. –  Kevin Hogg Jun 27 at 11:55

A practical example may be found here:

http://www.ytechie.com/2009/02/using-c-yield-for-readability-and-performance.html

There are a number of advantages of using yield over standard code:

  • If the iterator is used to build a list then you can yield the return and the caller can decide whether he wants that result in a list, or not.
  • The caller may also decide to cancel the iteration for a reason that is outside of the scope of what you are doing in the iteration.
  • Code is a bit shorter.

However, as Jan_V said (just beat me to it by a few seconds :-) you can live without it because internally the compiler will produce code almost identical in both cases.

share|improve this answer

Here's an example:

https://bitbucket.org/ant512/workingweek/src/a745d02ba16f/source/WorkingWeek/Week.cs#cl-158

The class performs date calculations based on a working week. I can tell an instance of the class that Bob works 9:30 to 17:30 every week day with an hour's break for lunch at 12:30. With this knowledge, the AscendingShifts() function will yield working shift objects between the supplied dates. To list all of Bob's working shifts between Jan 1 and Feb 1 this year, you'd use it like this:

foreach (var shift in week.AscendingShifts(new DateTime(2011, 1, 1), new DateTime(2011, 2, 1)) {
    Console.WriteLine(shift);
}

The class doesn't really iterate over a collection. However, the shifts between two dates can be thought of as a collection. The yield operator makes it possible to iterate over this imagined collection without creating the collection itself.

share|improve this answer

I have a small db data layer that has a command class in which you set the SQL command text, the command type, and return a IEnumerable of 'command parameters'.

Basically the idea is to have typed CLR commands instead of manually filling SqlCommand properties and parameters all the time.

So there is a function that looks like this:

IEnumerable<DbParameter> GetParameters()
{
    // here i do something like

    yield return new DbParameter { name = "@Age", value = this.Age };

    yield return new DbParameter { name = "@Name", value = this.Name };
}

The class that inherits this command class has the properties Age and Name.

Then you can new up a command object filled its properties and pass it to a db interface which actually does the command call.

All in all makes it really easy to work with SQL commands and keep them typed.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.