When I started, I thought that this might be a hairy part of the problem, but it turned out to be trivial.
My guess was based on the fact that my original IEnumerator implementation maintains a version stamp from the collection that it is enumerating. Any operation on the collection increments its version number and thus the enumerator no longer matches and refuses to operate. This is in strict adherence to the documented contract for the IEnumerator interface.
To get the same logic using iterators, the code is as follows:
public virtual IEnumerator<T> GetEnumerator()
for (int i = 0, version = this.version; i < this.size; i++)
if (this.version == version)
yield return this.nodeArray[i];
throw new InvalidOperationException(Resources.Enumerator_HeapModified);
Iterators are basically an inline code generator that creates a small state-machine based enumerator implementation. I found that I needed to have a look at the generated code using Reflector to convince myself of the correctness of the positioning of the
version = this.version initializer. Happily it is in just the right place.
BTW, Wesner Moise has a great article about pushing iterators further into a pipelined programming model.