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.

<strong>C#</strong> 2: simple iterators with yield statements169■ None of the code we wrote <strong>in</strong> GetEnumerator is called until the first call toMoveNext.■ Call<strong>in</strong>g MoveNext is the place all the work gets done; fetch<strong>in</strong>g Current doesn’trun any of our code.■ The code stops execut<strong>in</strong>g at yield return and picks up aga<strong>in</strong> just afterwards atthe next call to MoveNext.■ We can have multiple yield return statements <strong>in</strong> different places <strong>in</strong> the method.■ The code doesn’t end at the last yield return—<strong>in</strong>stead, the call to MoveNextthat causes us to reach the end of the method is the one that returns false.There are two th<strong>in</strong>gs we haven’t seen yet—an alternative way of halt<strong>in</strong>g the iteration,and how f<strong>in</strong>ally blocks work <strong>in</strong> this somewhat odd form of execution. Let’s take alook at them now.6.2.3 Advanced iterator execution flowIn normal methods, the return statement has two effects: First, it supplies the valuethe caller sees as the return value. Second, it term<strong>in</strong>ates the execution of the method,execut<strong>in</strong>g any appropriate f<strong>in</strong>ally blocks on the way out. We’ve seen that the yieldreturn statement temporarily exits the method, but only until MoveNext is calledaga<strong>in</strong>, and we haven’t exam<strong>in</strong>ed the behavior of f<strong>in</strong>ally blocks at all yet. How can wereally stop the method, and what happens to all of those f<strong>in</strong>ally blocks? We’ll startwith a fairly simple construct—the yield break statement.ENDING AN ITERATOR WITH YIELD BREAKYou can always f<strong>in</strong>d a way to make a method have a s<strong>in</strong>gle exit po<strong>in</strong>t, and many peoplework very hard to achieve this. 3 The same techniques can be applied <strong>in</strong> iteratorblocks. However, should you wish to have an “early out,” the yield break statement isyour friend. This effectively term<strong>in</strong>ates the iterator, mak<strong>in</strong>g the current call to Move-Next return false.List<strong>in</strong>g 6.6 demonstrates this by count<strong>in</strong>g up to 100 but stopp<strong>in</strong>g early if it runs outof time. This also demonstrates the use of a method parameter <strong>in</strong> an iterator block, 4and proves that the name of the method is irrelevant.List<strong>in</strong>g 6.6Demonstration of yield breakstatic IEnumerable CountWithTimeLimit(DateTime limit){for (<strong>in</strong>t i=1; i = limit){yield break;Stops if ourtime is up3I personally f<strong>in</strong>d that the hoops you have to jump through to achieve this often make the code much harderto read than just hav<strong>in</strong>g multiple return po<strong>in</strong>ts, especially as try/f<strong>in</strong>ally is available for cleanup and youneed to account for the possibility of exceptions occurr<strong>in</strong>g anyway. However, the po<strong>in</strong>t is that it can all be done.4Note that methods tak<strong>in</strong>g ref or out parameters can’t be implemented with iterator blocks.Licensed to Rhona Hadida

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

Saved successfully!

Ooh no, something went wrong!