13.07.2015 Views

C# in Depth

C# in Depth

C# in Depth

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

Create successful ePaper yourself

Turn your PDF publications into a flip-book with our unique Google optimized e-Paper software.

Real-life example: iterat<strong>in</strong>g over ranges175■ We want to be able to f<strong>in</strong>d out whether a particular value is with<strong>in</strong> the range.■ We want to be able to iterate through the range easily.The last po<strong>in</strong>t is obviously the most important one for this chapter, but the othersshape the fundamental decisions and ask further questions. In particular, it seemsobvious that this should use generics, but should we allow any type to be used for thebounds of the range, us<strong>in</strong>g an appropriate IComparer, or should we only allow typesthat implement IComparable, where T is the same type? When we’re iterat<strong>in</strong>g, howdo we move from one value to another? Should we always have to be able to iterateover a range, even if we’re only <strong>in</strong>terested <strong>in</strong> the other aspects? Should we be able tohave a “reverse” range (<strong>in</strong> other words, one with a start that is greater than the end,and therefore counts down rather than up)? Should the start and end po<strong>in</strong>ts be exclusiveor <strong>in</strong>clusive?All of these are important questions, and the normal answers would promote flexibilityand usefulness of the type—but our overrid<strong>in</strong>g priority here is to keep th<strong>in</strong>gssimple. So:■ We’ll make comparisons simple by constra<strong>in</strong><strong>in</strong>g the range’s type parameter T toimplement IComparable.■ We’ll make the class abstract and require a GetNextValue method to be implemented,which will be used dur<strong>in</strong>g iteration.■ We won’t worry about the idea of a range that can’t be iterated over.■ We won’t allow reverse ranges (so the end value must always be greater than orequal to the start value).■ Start and end po<strong>in</strong>ts will both be <strong>in</strong>clusive (so both the start and end po<strong>in</strong>ts areconsidered to be members of the range). One consequence of this is that wecan’t represent an empty range.The decision to make it an abstract class isn’t as limit<strong>in</strong>g as it possibly sounds—itmeans we’ll have derived classes like Int32Range and DateTimeRange that allow you tospecify the “step” to use when iterat<strong>in</strong>g. If we ever wanted a more general range, wecould always create a derived type that allows the step to be specified as a Converterdelegate. For the moment, however, let’s concentrate on the base type. With all therequirements specified, 8 we’re ready to write the code.6.3.3 Implementation us<strong>in</strong>g iterator blocksWith <strong>C#</strong> 2, implement<strong>in</strong>g this (fairly limited) Range type is remarkably easy. The hardestpart (for me) is remember<strong>in</strong>g how IComparable.CompareTo works. The trick I usuallyuse is to remember that if you compare the return value with 0, the result is the sameas apply<strong>in</strong>g that comparison operator between the two values <strong>in</strong>volved, <strong>in</strong> the orderthey’re specified. So x.CompareTo(y) < 0 has the same mean<strong>in</strong>g as x < y, for example.8If only real life were as simple as this. We haven’t had to get project approval and specification sign-off froma dozen different parties, nor have we had to create a project plan complete with resource requirements.Beautiful!Licensed to Rhona Hadida

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

Saved successfully!

Ooh no, something went wrong!