Oh that Iterators!! They are damn lazy.

You might know about Iterators which was introduced way back with C# 2.0. It provides a nice way to iterate a collection incredibly easy with yield keyword.

If you think you knew about Iterators already, let’s play a guessing game. Follow the code snippet below and guess what is the output of the program.

What do you expect that the above code will do when executed?

  1. Prints Program completed successfully” to the console.
  2. Crashes with ArgumentOutOfRangeException.
  3. Something else ?

Wait! Before you take a guess read the code again carefully. There is a chance that you could have overlooked.

Ok, If you have guessed the answer is A then you probably have good understanding of the Iterators; Yes it is the correct answer. I don’t have much to say for you. This post is for readers who took a wrong guess as B. I don’t even think someone would have chosen C, If you did — Sorry for confusing you by adding C as an option here.

At this point can you guess what could be the reason behind this program just prints  Program completed successfully” to the console given that previous line which calls the method GetGumbers(-1) should have thrown exception?

Yes you guessed it right. Iterators are damn lazy; this is what called as deferred execution. Compiler will transform the code inside the Iterator method to a state machine which doesn’t changes the semantics of the code.  When you  call IEnumerator.MoveNext() state machine will advance its state to yield next result. You will be calling it implicitly if you’re using foreach statement. Enumerable.ToArray() or Enumerable.ToList() can also do that. I don’t want to repeat the implementation details here and bore you; if you’re curious about the implementation details of Iterator blocks you will find comprehensive article of Jon Skeet very helpful.

In short Iterator blocks starts executing only when the first call to IEnumerator.MoveNext() has been made.

If I were to ask you a question “Is LINQ Lazy ?” you would probably say “Oh yes LINQ is lazy, It defers the execution, blah blah blah” without even knowing how.

Yes you’re absolutely right that LINQ is lazy but how? Because most of  the methods defined in LINQ is implemented using Iterator blocks.  Because the Iterators are lazy –LINQ is lazy.

Have you ever peeked into the implementation details of LINQ methods and wondered why there are pair of methods for each operation one is public part of the API and another is private with “Iterator” suffix ? You can see {Where, WhereIterator}, {Union, UnionIterator}, {Select, SelectIterator}. If you observed properly you could even notice that public methods validates the input and calls private Iterator method and  XXXIterator method doesn’t validates any argument. Can you guess why? At this point you should be able to guess.

As illustrated with the code sample above the laziness of Iterator blocks will give you surprise when exception  is thrown within the Iterator blocks; They are not thrown until the first call to IEnumerator.MoveNext() has been made. This is the reason why you should always validate the arguments in a separate method other than Iterator method.

Summary

What you see is not what gets compiled always. It is very common to overlook the code which uses iterator blocks even if you understand it very well. Take some care while reading code with Iterator blocks –you might overlook otherwise.