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.

90 CHAPTER 3 Parameterized typ<strong>in</strong>g with generics3.4.3 Generic iterationOne of the most common operations you’ll want to perform on a collection (usuallyan array or a list) is to iterate through all its elements. The simplest way of do<strong>in</strong>g thatis usually to use the foreach statement. In <strong>C#</strong> 1 this relied on the collection eitherimplement<strong>in</strong>g the System.Collections.IEnumerable <strong>in</strong>terface or hav<strong>in</strong>g a similarGetEnumerator() method that returned a type with a suitable MoveNext() methodand Current property. The Current property didn’t have to be of type object—andthat was the whole po<strong>in</strong>t of hav<strong>in</strong>g these extra rules, which look odd on first sight. Yes,even <strong>in</strong> <strong>C#</strong> 1 you could avoid box<strong>in</strong>g and unbox<strong>in</strong>g dur<strong>in</strong>g iteration if you had acustom-made enumeration type.<strong>C#</strong> 2 makes this somewhat easier, as the rules for the foreach statement have beenextended to also use the System.Collections.Generic.IEnumerable <strong>in</strong>terfacealong with its partner, IEnumerator. These are simply the generic equivalents ofthe old enumeration <strong>in</strong>terfaces, and they’re used <strong>in</strong> preference to the nongeneric versions.That means that if you iterate through a generic collection of value type elements—List,for example—then no box<strong>in</strong>g is performed at all. If the old<strong>in</strong>terface had been used <strong>in</strong>stead, then although we wouldn’t have <strong>in</strong>curred the box<strong>in</strong>gcost while stor<strong>in</strong>g the elements of the list, we’d still have ended up box<strong>in</strong>g them whenwe retrieved them us<strong>in</strong>g foreach!All of this is done for you under the covers—all you need to do is use the foreachstatement <strong>in</strong> the normal way, us<strong>in</strong>g the type argument of the collection as the type ofthe iteration variable, and all will be well. That’s not the end of the story, however. Inthe relatively rare situation that you need to implement iteration over one of your owntypes, you’ll f<strong>in</strong>d that IEnumerable extends the old IEnumerable <strong>in</strong>terface, whichmeans you’ve got to implement two different methods:IEnumerator GetEnumerator();IEnumerator GetEnumerator();Can you see the problem? The methods differ only <strong>in</strong> return type, and the rules of<strong>C#</strong> prevent you from writ<strong>in</strong>g two such methods normally. If you th<strong>in</strong>k back to section2.2.2, we saw a similar situation—and we can use the same workaround. If youimplement IEnumerable us<strong>in</strong>g explicit <strong>in</strong>terface implementation, you can implementIEnumerable with a “normal” method. Fortunately, because IEnumeratorextends IEnumerator, you can use the same return value for both methods, andimplement the nongeneric method by just call<strong>in</strong>g the generic version. Of course,now you need to implement IEnumerator and you quickly run <strong>in</strong>to similar problems,this time with the Current property.List<strong>in</strong>g 3.9 gives a full example, implement<strong>in</strong>g an enumerable class that always justenumerates to the <strong>in</strong>tegers 0 to 9.List<strong>in</strong>g 3.9 A full generic enumeration—of the numbers 0 to 9class Count<strong>in</strong>gEnumerable: IEnumerable{public IEnumerator GetEnumerator()BImplementsIEnumerableimplicitlyLicensed to Rhona Hadida

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

Saved successfully!

Ooh no, something went wrong!