Advertisment

Whidbey: Working with Iterators

author-image
PCQ Bureau
New Update

Iterators, the magic of Whidbey C# compiler, let you write a collection type without even implementing IEnumerator. But, to understand how Iterators help us and how they work internally, we need to first look at how collections are implemented today. So, let's get started.

Advertisment

How collections work today 



Collection, in its basic sense, is a container that holds objects of the same type. Developers work with collections in two different ways: One, they consume collections by iterating over them and working with the values they return and two, they implement collection types that can be iterated.

Typically, when one needs to implement a collection type, the type must implement a method by the name GetEnumerator that will return a reference to a type that implements the IEnumerator interface (which is defined in the System.Collections namespace). Here's an example of a type that implements a collection of integers.

Snapshot
Applies to .Net developers
Usp Easier development methodology
Advertisment

internal class MyIntCollection



{


public IEnumerator GetEnumerator()


{


return new MyIntEnumerator();


}


}












Above is the minimum code that you will need to write to start implementing a type that maintains a collection. However, the next major step, and the most important one, is where the developer needs to implement another type that implements the IEnumerator interface, and does the work of enumerating over the collection being maintained. In the above example, this type is MyIntEnumerator and is implemented as shown below.

internal class MyIntEnumerator: IEnumerator



{


// member working fields come here…


public MyIntEnumerator()


{


// perform some initialization, like setting the array size


}


public void Reset()


{


// reset the starting Index...


iCurIndex = -1;


bReachedEnd = false;


}


public bool MoveNext()


{


// move to the next value in collection


return true;


}


public object Current


{


// check for the valid current value and return it…


}


}






















Compiler’s implementation of the class that implements IEnumerator
Advertisment

As you can see, this type:






l Does the hard work of maintaining the collection


l Needs to implement the IEnumerator interface so that the consumers can iterate over the collection data


l The developer of the type is responsible for coding all the implementation





The collection consume code is shown below.





MyIntCollection collInt = new MyIntCollection();


foreach(int iNum in collInt)


Console.WriteLine("{0} ", iNum);








Now, consider this: What if your class library has to implement multiple collections? The developers will need to do the plumbing work over and over again, in addition to implementing the IEnumerator repeatedly. Not only does this result in zero productivity gain, but also (almost) functional duplicity.

With Whidbey C#, all this comes to an end, with the compiler conjuring some more magic to ease the developers' lives. Let's see how.

Advertisment

Collections with Iterators



In Whidbey C#, a new keyword has been introduced that goes by the name yield. Developers of the Ruby programming language may be familiar with this. And once a developer uses yield in his code, he is freed from the implementation of IEnumerator! Yes, that's done by the compiler for you, during compile time.

Thus, Iterators provide a more simplified and clean way of working with collections and enumerators.

To understand the concept better, let's have a look at the Iterator version of the MyIntCollection class.






internal class MyIntCollection


{


private int iCount;


private int<> iData;


private int iCurIndex;


public MyIntCollection()


{


iCount = 10;


iData = new int;


// fill up with some data


for(int i=0;i
iData = i + 1;



// set the starting index


iCurIndex = 0;


}


public IEnumerator GetEnumerator()


{


while(iCurIndex
yield iData;



}


}


















Advertisment
Though you used the yield keyword in the GetEnumerator method implementation, there's no reference to the same when you view the ILshows the resulting output

And that's all there is to it. No separate implementation of IEnumerator follows, unlike the previous example. Notice that although the GetEnumerator is supposed to return a type implementing IEnumerator, there's no such return statement within the method implementation that indicates so.

However, you do see the yield keyword in action, which yields the current value for the collection as per the enumeration cycle. But iData is an integer array, not IEnumerator implementation. So, isn't that a compiler error? No, it isn't. Let's see why.



Iterators–inside yield...

Advertisment

GetEnumerator does return an implementation of IEnumerator, even though the developer has not implemented it. When the compiler encounters the use of the yield keyword, it shall automatically produce code for such an implementation, behind the scenes. If you ILDASM (under Whidbey) the source code of the Iterators project that accompanies this article, you will see the compiler implemented version of the class that implements

IEnumerator.

As expected, though you used the yield keyword in the GetEnumerator method implementation, there's no reference to the same when you view the IL. 

On the contrary, you will see the instantiation of the  compiler-created class that implements

IEnumerator. This is expected since this is how enumerable types are implemented. We do the same work today manually. With Whidbey, this will be done by the compiler.

Advertisment
The ILDASM (under Whidbey) shows IEnumerator

If you proceed to expand the node of the compiler-created IEnumerator implementation class, you will see the familiar implementations of Reset, MoveNext methods and the Current property.

All the work that the developer had to do regarding the implementation of looping through the values to be returned from the enumeration, maintaining counts, resetting the counters is now already done by the compiler. You simply use yield.

Finally



So, with this article we have concluded our coverage of the four core new enhancements in Whidbey: Generics, Partial Types, Anonymous Methods and Iterators. Keep the source code handy so that you can work with the Whidbey Beta when it comes out pretty soon.

Continuing our journey of exploring Whidbey, in our forthcoming issues we will talk about ADO.NET 2.0 and see how it has been enhanced to make the developer's more productive.

Kumar Gaurav Khanna 



wintoolzone.com

Advertisment