How to implement IEnumerable in my Dictionary wrapper class that implements IEnumerable <Foo>?
I am trying to create a wrapper for Dictionary<String,Foo> .
Dictionary<String,Foo> implements IEnumerable<KeyValuePair<String,Foo>> , but I want my wrapper class to implement IEnumerable<Foo> . So I tried this:
public class FooCollection : IEnumerable<Foo> { private Dictionary<string, Foo> fooDictionary = new Dictionary<string, Foo>(); public IEnumerator<Foo> GetEnumerator() { return fooDictionary.Values.GetEnumerator(); } // Other wrapper methods omitted } However, I get this error:
'FooCollection' does not implement a member of the 'System.Collections.IEnumerable.GetEnumerator ()' interface. 'FooCollection.GetEnumerator ()' cannot implement 'System.Collections.IEnumerable.GetEnumerator ()' because it does not have the corresponding return type 'System.Collections.IEnumerator'.
However, I do not understand this error because FooCollection.GetEnumerator() returns IEnumerator<Foo> , and IEnumerator<Foo> returns IEnumerator .
EDIT:
A solution explicitly implementing IEnumerator.GetEnumerator() works. However, now I wonder why, when I "Go to Definition" on List<T> , I see only one GetEnumerator definition: public List<T>.Enumerator GetEnumerator();
Apparently, List<T> may have a single GetEnumerator method that returns something that implements both IEnumerator<T> and IEnumerator , but should there be one method for each of them?
EDIT:
As LukeH answered below, List<T> includes explicit interface implementations. Apparently, Visual Studio just doesn't list them when creating labels from metadata. (See Previous question: Why VS interface metadata view does not display explicit interface elements implemented in the interface )
Before posting this question, I tried checking List<T> (via "Go to Definition" in Visual Studio) to see if I need to implement multiple versions of GetEnumerator. I think this was not the most reliable way to check.
Anyway, I mark this as an answer. Thank you for your help.
When implementing IEnumerable<T> you must also explicitly implement IEnumerable.GetEnumerator() . The method for the general interface is not valid as an implementation for a non-standard contract. You can call one another, or since you have a child whose counter you are using, just copy / paste;
using System.Collections; using System.Collections.Generic; public class FooCollection : IEnumerable<Foo> { private Dictionary<string, Foo> fooDictionary = new Dictionary<string, Foo>(); public IEnumerator<Foo> GetEnumerator() { return fooDictionary.Values.GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { //forces use of the non-generic implementation on the Values collection return ((IEnumerable)fooDictionary.Values).GetEnumerator(); } // Other wrapper methods omitted } The problem is that in .NET there is no such thing as return type covariance in .NET - IEnumerator M() and IEnumerator<Foo> M() are completely different methods.
The workaround is that you must explicitly implement the non-generic version:
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { // this calls the IEnumerator<Foo> GetEnumerator method // as explicit method implementations aren't used for method resolution in C# // polymorphism (IEnumerator<T> implements IEnumerator) // ensures this is type-safe return GetEnumerator(); } While the generic IEnumerable {T} inherit is IEnumerable, you must also implement IEnumerable.GetEnumerator() . You can do it explicitly:
IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } You already had several answers to your main question. I will answer the question raised in your editing ...
The List<T> class actually has three different GetEnumerator methods: a public method that is called when a compilation time instance is entered as a List<T> , and two explicit interface implementations for matching IEnumerable / IEnumerable<T> contracts. The enumeration objects returned by all three methods are still of type List<T>.Enumerator behind the scenes.
// Public method public List<T>.Enumerator GetEnumerator() { /* ... */ } // IEnumerable<T> explicit interface implementation IEnumerator<T> IEnumerable<T>.GetEnumerator() { /* ... */ } // IEnumerable explicit interface implementation IEnumerator IEnumerable.GetEnumerator() { /* ... */ } Here is the IEnumerable declaration:
public interface IEnumerable<out T> : IEnumerable { new IEnumerator<T> GetEnumerator(); } Pay attention to the new keyword.
Here is the IEnumerable declaration:
public interface IEnumerable { IEnumerator GetEnumerator(); } So now you have the GetEnumerator method, but which of these two are you implementing? Therefore, you need to add an explicit implementation of the non-generic version:
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { return this.GetEnumerator(); }