yield return Has always been one of the hardest things to understand.
Now that I’ve understood this (not thoroughly, but enough to explain it), it’s my turn to share my learning.
So what yes
yield return You mean? How does this relate to item collections?
Suppose you return a collection of items and you need to repeat them.
A first approach can be to create a list with all the items, return it to the caller and iterate the collection:
IEnumerable<int> WithList() List<int> items = new List<int>(); for (int i = 0; i < 10; i++) Console.WriteLine($"Added item i"); items.Add(i); return items; void Main() var items = WithList(); foreach (var i in items) Console.WriteLine($"This is Mambo number i");
This section creates the entire collection and then prints the entries within this list. In the console, you will see this text:
Added item 0 Added item 1 Added item 2 Added item 3 Added item 4 Added item 5 Added item 6 Added item 7 Added item 8 Added item 9 This is Mambo number 0 This is Mambo number 1 This is Mambo number 2 This is Mambo number 3 This is Mambo number 4 This is Mambo number 5 This is Mambo number 6 This is Mambo number 7 This is Mambo number 8 This is Mambo number 9
This means that if you need to run on a collection with a million items, you will first create all the items, and then perform actions on each of them. This approach has two main drawbacks: it is slow (especially if you only need to work with a subset of these items), and takes up a lot of memory.
We can use another approach: Use
yield return Keywords:
IEnumerable<int> WithYield() for (int i = 0; i < 10; i++) Console.WriteLine($"Returning item i"); yield return i; void Main() var items = WithYield(); foreach (var i in items) Console.WriteLine($"This is Mambo number i");
In this method, the order of the messages is changed:
Returning item 0 This is Mambo number 0 Returning item 1 This is Mambo number 1 Returning item 2 This is Mambo number 2 Returning item 3 This is Mambo number 3 Returning item 4 This is Mambo number 4 Returning item 5 This is Mambo number 5 Returning item 6 This is Mambo number 6 Returning item 7 This is Mambo number 7 Returning item 8 This is Mambo number 8 Returning item 9 This is Mambo number 9
Therefore, instead of creating the entire list, we create one item at a time, and only when necessary.
As I said before, there are some benefits with
yield: The app has higher performance when it comes to both execution time and memory usage.
It’s like an automatic iterator: every time you get a result, the iterator advances to the next item.
Just a note:
yield Works only for recurring methods
You can not use it in a method that returns, for example,
List<T>, Because as the error message says,
X’s body can not be an iterator block because
List<int>Is not a type of iterator interface
If you use NUnit As a test package, you have probably already used this keyword.
In particular, when using
TestCaseSource Feature, you specify the name of the department that issues the test cases.
public class MyTestClass [TestCaseSource(typeof(DivideCases))] public void DivideTest(int n, int d, int q) Assert.AreEqual(q, n / d); class DivideCases : IEnumerable public IEnumerator GetEnumerator() yield return new object 12, 3, 4 ; yield return new object 12, 2, 6 ; yield return new object 12, 4, 3 ;
When performing the tests, the iterator returns a test case at a time, without creating a complete list of test cases.
The previous section was taken directly from the NUnit documentation for
TestCaseSource attribute, Which you can find here.
yield Is a rather difficult keyword to understand.
For further reading, go to The official documents.
And if you like, check out the conversation I had about this keyword On Twitter.