32

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
  • 22,411
  • 10
  • 48
  • 86
  • 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

51

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
  • 1,023,142
  • 271
  • 3,287
  • 2,928
  • 1
    Thank you, I didn't know IEnumerable implements IEnumerable (though it sounds obvious :P) – BlackBear Jan 06 '12 at 15:54
  • 12
    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
  • @JimBalter: PJTraill's comments still is the right answer in certain contexts, when only the "incidental thing" is wrong. At least is the first thing to check even now in 2023. if you do a lot of drafts in LinqPad and DotFiddleNet because they do not automatically import the correct Namespace, and the error msg is far from helpful. – Marcelo Scofano Diniz May 30 '23 at 19:45
  • My comment was factually correct. – Jim Balter May 31 '23 at 20:36
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
  • 647,829
  • 179
  • 1,238
  • 2,067
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
  • 41,274
  • 9
  • 83
  • 114
5

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
  • 1,023
  • 14
  • 27
4

Add the following method:

IEnumerator IEnumerable.GetEnumerator()
{
    return this.GetEnumerator();
}
Chris Shain
  • 50,833
  • 6
  • 93
  • 125
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,995
  • 15
  • 85
  • 141
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
  • 16
  • 33