Interface implementations and return types

The List<T> class implements the IEnumerable<T> interface. It has a GetEnumerator method that returns a List<T>.Enumerator .

I have a class as shown below that gives a compilation error saying that the return type of GetEnumerator does not 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 a member of the 'System.Collections.Generic.IEnumerable.GetEnumerator ()' interface. 'Entities.Helpers.InsertionSortedSet.GetEnumerator ()' cannot implement 'System.Collections.Generic.IEnumerable.GetEnumerator ()' because it does not have the corresponding return type 'System.Collections.Generic.IEnumerator'.

Given that the List<T> seems to be returning its own Enumerator class (and not the interface), and yet it implements the Enumeration<T> interface, I got confused as I can’t understand that this class has changed.

What happened to my setting, which causes it to crash, where does List<T> work?


I want to return the InsertionSortedSet<T>.Enumerator , not the interface, as it avoids the box I need to cut.

+4
source share
3 answers

He complains that GetEnumerator () returns an IEnumerator<T> for the IEnumerable<T> interface. To satisfy, your type should return IEnumerator<T> (and explicit for IEnumerator ).

But in many cases, it is desirable for the class to return a more specific type than the interface indicates, but interfaces do not allow such covariant return types. To do this, you can do what List<T> has and has GetEnumerator() to return your specific enumerator, but you must also implement explicit implementations for IEnumerable.GetEnumerator() , which returns IEnumerator and for IEnumerable<T>.GetEnumerator() which returns 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 will see that it implements GetEnumerator() three times:

  • Once explicitly for IEnumerable<T>
  • Once explicitly for Enumerable
  • Once with a very specific list

You can do the same in your class if you want (which you like, so you started), but if you do, you must explicitly implement IEnumerable<T>.GetEnumerator() and IEnumerable.GetEnumerator()

If you move on to the definition, you can see other definitions in the object browser by selecting the different interfaces that it satisfies (or by assigning the List<T> instance to the IEnumerable or IEnumerable<T> link and going to the definition):

Screenshot of Object Explorer

+7
source

To allow class iteration to be repeated using foreach , you do not need to implement any interface. All you need is a GetEnumerator method that returns your Enumerator<T> .

But if you want your class to support the standard iterative interface IEnumerable<T> , you can implement its explication: IEnumerable<T>.GetEnumerator() { return GetEnumerator(); } IEnumerable<T>.GetEnumerator() { return GetEnumerator(); }

0
source

What you are looking for is called return type covariance, here Does C # support type type covariance?

This can be achieved by using an explicit interface implementation to return IEnumerator<T> and implementing a public method with the same name to return an Enumerator.

0
source

Source: https://habr.com/ru/post/1389740/


All Articles