The List<T>
class implements the IEnumerable<T>
interface. It has a method GetEnumerator
that returns a List<T>.Enumerator
.
I have a class as below, which gives a compile error saying the return type of GetEnumerator
doesn't match the interface.
public class InsertionSortedSet<T> : IEnumerable<T>
{
public struct Enumerator : IEnumerator<T>
{
// Required interface implemented
}
// Other interface methods implemented
public Enumerator GetEnumerator()
{
return new Enumerator(this);
}
}
'Entities.Helpers.InsertionSortedSet' does not implement interface member 'System.Collections.Generic.IEnumerable.GetEnumerator()'. 'Entities.Helpers.InsertionSortedSet.GetEnumerator()' cannot implement 'System.Collections.Generic.IEnumerable.GetEnumerator()' because it does not have the matching return type of 'System.Collections.Generic.IEnumerator'.
Given that List<T>
seems to return it's own Enumerator
class (not the interface) and yet it does implement the Enumeration<T>
interface I'm confused, as I can't see what i've got different to that class.
List<T>
works?I want to return a InsertionSortedSet<T>.Enumerator
rather than the interface as it avoids boxing, which I need to cut out.
It's complaining because GetEnumerator() returns IEnumerator<T>
for the IEnumerable<T>
interface. To satisfy, your type must return IEnumerator<T>
(and an explicit one for IEnumerator
as well).
But, many times it's desirable for a class to return a more specific type than the interface specifies, but interfaces don't allow for covariant return types like that. So to do this, you can do what List<T>
does and have GetEnumerator()
return your specific enumerator, but you must also implement explicit implementations for IEnumerable.GetEnumerator()
that returns an IEnumerator
and for IEnumerable<T>.GetEnumerator()
that returns an IEnumerator<T>
:
// This is your specific version, like List<T> does
public Enumerator GetEnumerator()
{
return new Enumerator(this);
}
// This is the one with the return value IEnumerator<T> expects
IEnumerator<T> IEnumerable<T>.GetEnumerator()
{
return new Enumerator(this);
}
// Plus, it also expects this as well to satisfy IEnumerable
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
If you look at List<T>
you'll see that it implements GetEnumerator()
three times:
IEnumerable<T>
Enumerable
You could do the same in your class if you wish (which it sould like is the way you began) but if you do that you must explicitly implement IEnumerable<T>.GetEnumerator()
and IEnumerable.GetEnumerator()
If you navigate to the definition, you can see the other definitions in the object browser by selecting the different interfaces it satisfies (or by assigning a List<T>
instance to an IEnumerable
or IEnumerable<T>
reference and going to definition):