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):
To allow a class to be iterated using foreach
no need to implement any interface. All what you need is implementing GetEnumerator method that returns your Enumerator<T>
.
But if you want your class to support standard iteration interface IEnumerable<T>
you may implement it explicity: IEnumerable<T>.GetEnumerator() { return GetEnumerator(); }
IEnumerable<T>.GetEnumerator() { return GetEnumerator(); }
What you are looking for is called return type covariance, more here Does C# support return type covariance?
This can be achieved by using explicit implementation of interface to return IEnumerator<T>
and implement public method of same name to return Enumerator.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.