Say you want to implement a class that implements the IEnumerable
interface in C#. Then you have two choices, either to implement the old-style non-generic IEnumerable
interface or you can implements the generic IEnumerable<T>
interface. Given those choices we of course want to implement the new generic version of the interface. Because otherwise lots of boxing and unboxing will happen when T
is a value type, with the non-generic version you will not be able to conveniently use the Current
property of your enumerator, and for general type-safety goodness.
Thus, you set out to implement the generic version. For example, let say we want to implement a class that enumerates all the integers staring from a given offset. First we might try this:
using System.Collections.Generic; class Ints : IEnumerable<int> { private readonly int offset; public Ints(int o) { offset = o; } public IEnumerator<int> GetEnumerator() { int i = offset; while( true ) yield return i++; } }
But then the compiler complains:
error CS0535: 'Ints' does not implement interface member 'System.Collections.IEnumerable.GetEnumerator()'
Thank you for letting us know nice compiler. But we don’t want Ints
to implement the non-generic interface. We want it to implement the generic interface.
Reading up on the documentation will reveal that the generic interface inherits from the non-generic interface. What a wonderful design. Thankfully we can make a general work-around for this design flaw in the library. Just add a non-generic method that calls the generic method:
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { return GetEnumerator(); }
Once the author of my favorite C# book returns from vacation. I’ll complain to him that the section about IEnumerable
didn’t make it clear that if you want to implement the generic interface you also have to implement the non-generic interface.
Update: It turns out that the errata to C# Precisely already mentions this curriousity.
hey! thanks for this. ive been tearing my hair out trying to figure out whats going on here. didnt make any sense AT all. some of these little nuances can drive you nuts.
Very Helprful!
Argh!!!! curse the IEnumerator designer who wasted hours of my time on this compile time error!!!!
Ditto. Many thanks!
Interesting. I originally got the same compiler error (does not implement interface member ‘System.Collections.IEnumerable.GetEnumerator()’). I then inserted the non-generic method call. Now the compiler error says I’m not implementing IEnumerable.GetEnumerator(). That method, of course, has been in the class all along (and it is public).The difference here is that my class (that implements IEnumerable) is also generic. In any case, I still don’t know what I should do.
Rubio:
Is it possible for you to post a minimal example showing the error. Similar to the
Ints
example in the post?For example, here is a generic repeater class. That is, when you construct the class you give it an element to repeat and how many times it should be repeated.
Argh, there are several web sites that teach how to use iterators without mentioning this. Like this Microsoft article: http://msdn.microsoft.com/msdnmag/issues/04/05/C20/
One wonders why C# can’t supply the second GetEnumerator() function automatically.
Thanks.. well hard to get this .. they should publish this hack on msdn. I was totaly confused.
Thank you. Perfect explanation
Why is it that when I Google topics like these I have to go through 2 to 7 pages worth of nonsense and people who don’t know what they are talking about before I find something useful like this? seems like most the pages are on the proper syntax of the for-each loop not how to implement the interface correctly.
Thanks man! 🙂