31

I'm trying to write my own (simple) implementation of List. This is what I did so far:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace provaIEnum
{
    class MyList<T> : IEnumerable<T>
    {
        private T[] _array;
        public int Count { get; private set; }

        public MyList() { /* ... */ }
        public void Add(T element) { /* ... */ }

        // ...

        public IEnumerator<T> GetEnumerator()
        {
            for (int i = 0; i < Count; i++)
                yield return _array[i];
        }
    }

I'm getting an error about GetEnumerator though:

'provaIEnum.Lista' does not implement interface member 'System.Collections.IEnumerable.GetEnumerator()'. 'provaIEnum.Lista.GetEnumerator()' cannot implement 'System.Collections.IEnumerable.GetEnumerator()' because it does not have the matching return type of 'System.Collections.IEnumerator'.

I'm not sure if I understand what VS's trying to tell me and I have no idea how to fix it.

Thanks for your time

BlackBear
  • 21,554
  • 9
  • 45
  • 82
  • Note that you shouldn't write your enumerator like that since currently you can modify your internal array in a `foreach` (calling `Add` in foreach wont cause an exception). [See](http://stackoverflow.com/questions/24142614/when-should-i-separately-implement-ienumeratort) – nawfal Jul 08 '14 at 16:59
  • @nawfal good point, bugs are always watching us ;) – BlackBear Jul 08 '14 at 17:46

7 Answers7

49

Since IEnumerable<T> implements IEnumerable you need to implement this interface as well in your class which has the non-generic version of the GetEnumerator method. To avoid conflicts you could implement it explicitly:

IEnumerator IEnumerable.GetEnumerator()
{
    // call the generic version of the method
    return this.GetEnumerator();
}

public IEnumerator<T> GetEnumerator()
{
    for (int i = 0; i < Count; i++)
        yield return _array[i];
}
Darin Dimitrov
  • 994,864
  • 265
  • 3,241
  • 2,902
  • 1
    Thank you, I didn't know IEnumerable implements IEnumerable (though it sounds obvious :P) – BlackBear Jan 06 '12 at 15:54
  • 11
    Since you have not explicitly qualified `IEnumerator` and `IEnumerable.GetEnumerator` with `System.Collections.`, this will fail if you do not have `using System.Collections`, saying (pretty unhelpfully) that `IEnumerator` needs a generic argument! – PJTraill Apr 04 '16 at 16:42
  • 1
    @PJTraill This comment is the right answer (`IEnumerator` needs to be fully qualified to resolve conflicting with its generic variant). – yacc Aug 19 '18 at 19:46
  • 1
    ^ No, PJTraill's comment is not "the right answer", Darin gave the right answer. That you need the right using statements or else need to fully qualify the interface names is a good point, but is incidental. – Jim Balter Nov 13 '18 at 04:35
40

Read the error message more carefully; it is telling you exactly what you must do. You did not implement System.Collections.IEnumerable.GetEnumerator.

When you implement the generic IEnumerable<T> you have to also implement System.Collections.IEnumerable's GetEnumerator.

The standard way to do so is:

public IEnumerator<T> GetEnumerator () { whatever }
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
    return this.GetEnumerator();
}
Eric Lippert
  • 630,995
  • 172
  • 1,214
  • 2,051
11

You'll need to implement the non-generic GetEnumerator method as well:

IEnumerator IEnumerable.GetEnumerator()
{
    return GetEnumerator();
}

Since the IEnumerable<T> interface extends IEnumerable, you have to implement the methods declared on both.

Rich O'Kelly
  • 40,274
  • 9
  • 81
  • 111
4

I got similar problem,though I implemented also IEnumerable and IEnumerable. I was using custom type (Person class) than generic type T. For me the reason was, namespace was not included in the top of file.

using System.Collections; 

After adding the namespace it was fine for me.

RotatingWheel
  • 941
  • 9
  • 27
4

Add the following method:

IEnumerator IEnumerable.GetEnumerator()
{
    return this.GetEnumerator();
}
Chris Shain
  • 50,081
  • 5
  • 91
  • 124
2

There are two overloads of GetEnumerator() that you must implement. One comes from IEnumerable<T> and returns IEnumerator<T>. The other comes from IEnumerable and returns IEnumerator. The override should look like this:

IEnumerator IEnumerable.GetEnumerator()

This is because IEnumerable<T> implements IEnumerable.

Ilya Kogan
  • 21,366
  • 15
  • 81
  • 136
1

Since your class, MyList<T> inherits IEnumerable<out T> which in turn inherits the non-generic IEnumerable, you have two methods you need to implement:

IEnumerator<T> IEnumerable<T>.GetEnumerator()
        {
            throw new NotImplementedException();
        }

        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            throw new NotImplementedException();
        }

An easy way to do this is when you declare your class:

class MyList<T> : IEnumerable<T>

Right click the IEnumerable<T> text and select Implement Interface > Implement Interface Explictly from the context menu.

Michael Hornfeck
  • 1,242
  • 1
  • 15
  • 32