13.07.2015 Views

C# in Depth

C# in Depth

C# in Depth

SHOW MORE
SHOW LESS
  • No tags were found...

You also want an ePaper? Increase the reach of your titles

YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.

172 CHAPTER 6 Implement<strong>in</strong>g iterators the easy wayDateTime stop = DateTime.Now.AddSeconds(2);IEnumerable iterable = CountWithTimeLimit(stop);IEnumerator iterator = iterable.GetEnumerator();iterator.MoveNext();Console.WriteL<strong>in</strong>e ("Received {0}", iterator.Current);iterator.MoveNext();Console.WriteL<strong>in</strong>e ("Received {0}", iterator.Current);This time the “stopp<strong>in</strong>g” l<strong>in</strong>e is never pr<strong>in</strong>ted. It’s relatively rare that you’ll want to term<strong>in</strong>atean iterator before it’s f<strong>in</strong>ished, and it’s relatively rare that you’ll be iterat<strong>in</strong>gmanually <strong>in</strong>stead of us<strong>in</strong>g foreach, but if you do, remember to wrap the iterator <strong>in</strong> aus<strong>in</strong>g statement.We’ve now covered most of the behavior of iterator blocks, but before we endthis section it’s worth consider<strong>in</strong>g a few oddities to do with the current Microsoftimplementation.6.2.4 Quirks <strong>in</strong> the implementationIf you compile iterator blocks with the Microsoft <strong>C#</strong> 2 compiler and look at the result<strong>in</strong>gIL <strong>in</strong> either ildasm or Reflector, you’ll see the nested type that the compiler hasgenerated for us beh<strong>in</strong>d the scenes. In my case when compil<strong>in</strong>g our (evolved) firstiterator block example, it was called IterationSample.d__0 (wherethe angle brackets aren’t <strong>in</strong>dicat<strong>in</strong>g a generic type parameter, by the way). I won’t gothrough exactly what’s generated <strong>in</strong> detail here, but it’s worth look<strong>in</strong>g at it <strong>in</strong> Reflectorto get a feel for what’s go<strong>in</strong>g on, preferably with the language specification next toyou: the specification def<strong>in</strong>es different states the type can be <strong>in</strong>, and this descriptionmakes the generated code easier to follow.Fortunately, as developers we don’t need to care much about the hoops the compilerhas to jump through. However, there are a few quirks about the implementationthat are worth know<strong>in</strong>g about:■ Before MoveNext is called for the first time, the Current property will alwaysreturn null (or the default value for the relevant type, for the generic <strong>in</strong>terface).■ After MoveNext has returned false, the Current property will always return thelast value returned.■ Reset always throws an exception <strong>in</strong>stead of resett<strong>in</strong>g like our manual implementationdid. This is required behavior, laid down <strong>in</strong> the specification.■ The nested class always implements both the generic and nongeneric form ofIEnumerator (and the generic and nongeneric IEnumerable where appropriate).Fail<strong>in</strong>g to implement Reset is quite reasonable—the compiler can’t reasonably workout what you’d need to do <strong>in</strong> order to reset the iterator, or even whether it’s feasible.Arguably Reset shouldn’t have been <strong>in</strong> the IEnumerator <strong>in</strong>terface to start with, and Icerta<strong>in</strong>ly can’t remember the last time I called it.Implement<strong>in</strong>g extra <strong>in</strong>terfaces does no harm either. It’s <strong>in</strong>terest<strong>in</strong>g that if yourmethod returns IEnumerable you end up with one class implement<strong>in</strong>g five <strong>in</strong>terfacesLicensed to Rhona Hadida

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!