Skip to main content

Iterators in C#


Have you used yield keyword with c# any time ? I also never used Yield keyword prior to this article. The only thing that drove me to write this article is that Yield uses state machine while doing things.

I've some knowledge about state machines concept, which I've studied in my graduation course. But never saw something that uses state machines in practical.

Though yield offers a nice mechanism to preserve the state and offer a deferred execution, it is used less in the daily programming basis. But still it's good to know what this yield does.
Ok, let's get started.

An iterator is a method, get accessor, or operator that performs a custom iteration over an array or collection class by using the yield keyword
from MSDN
When the yield return statement is executed in the Iterator method, it returns the value immediately from the method, preserving the current state where it left. If the Iterator is called again, then the execution starts from the line where the method has paused it's execution previously. Behind the scenes it builds a state machine for doing this job.

Let me explain how to use iterator in a method, get accessor and in operator.

Let's have a simple example of returning the products by calling the GetProducts() method.

Note:

  1. An important point to note while using Iterators is that the return type of the Iterator must be IEnumerable, IEnumerator, IEnumerable<t>, or IEnumerator<t>.
  2. Iterators are available since the early releases of c#. Yield offers deferred execution in c#. In fact yield might be the debutant to use deferred execution.
The following code is responsible for calling the Iterator method

By returning an IEnumberable type from the GetProducts() method allows the caller to use foreach over the items.

Comprehension:
When yield return statement is first executed in the Iterator, it immediately returns the product name from the Iterator and writes "Product1" to the console. When the Iterator method is called once again it returns "Product2" from the Iterator method and written to the console and so forth. So, for the second execution instead of returning "Product1" from the method it returned "Product2" because it knows where it left and resumes the operation hence returning the second product.

I understand that you don't believe me what I've wrote above about the Yield keyword. Well, place a debugger at the starting curly brace of the Iterator method and try to step into it to see what is happening.

2. USING ITERATOR IN A GET ACCESSOR

For this example let's modify the above code a little bit to return the products and Ids from the get accessor. 
Comprehension:
When GetProducts property is accessed for, then the property returns the list of products with ids and names of the products each at a time.

3. USING ITERATOR IN AN OPERATOR
The implementation of yield in Operator is pretty much same as the implementation of yield in a Method except that this implementation uses operators to return things.

Let's consider a simple Fibonacci series example to demonstrate using iterator in operator.
Comprehension:
When Fibonnacci(5) is called, the value of "a" is returned from the Fibonacci method. Followed by b, followed by the numbers sequence of fibonacci series.

If you want to know how this state machine for yield keyword works, stay tuned for my upcoming post. If you are still stuck in debugging thing, please leave a comment I'll help you out.

Your thoughts, if any ?

Cheers
Karthik !

Comments

Popular posts from this blog

Losing precision after multiplication in SQL Server


Yesterday I was doing a little multiplication operation in SQL SERVER. The computation involves multiplication of two decimal numbers. A point to note here is that I've to be very careful while performing the calculations because it's a monetary thing. So, Whatever the calculation made, it must be very accurate such that I shouldn't miss any fractions as it costs in MILLIONS. The scenario is that I've two numbers, after multiplying each other I'm losing the precision of the values. I've tried to check my database for any faulty data that caused the issue. But the data is absolutely fine.