When does IEnumerable.GetEnumerator get called instead of IEnumerable<T>.GetEnumerator?

.net, c#, ienumerable, ienumerator

Solution

The other answers sort of miss the point.

Interfaces do not matter at all if the (compile-time) type of what is beeing `foreach`ed has a `public` non-generic non-static method called `GetEnumerator` which takes zero arguments. (The return type of this method can be anything, generic or non-generic: interfaces will not matter.)

So the reason why the first of your methods is called, is that this is the `public` method.

You can change that:

public class myWords : IEnumerable<string>
{
    string[] f = "I love you".Split(new string[]{"lo"},StringSplitOptions.RemoveEmptyEntries);

    IEnumerator<string> IEnumerable<string>.GetEnumerator()
    {
        return f.Select(s => s + "2").GetEnumerator();
    }

    public IEnumerator GetEnumerator()
    {
        return f.Select(s => s + "3").GetEnumerator();
    }
}

To prove that interfaces are not needed, try this:

public class myWords // no interfaces!
{
    string[] f = "I love you".Split(new string[]{"lo"},StringSplitOptions.RemoveEmptyEntries);

    public IEnumerator GetEnumerator()
    {
        return f.Select(s => s + "3").GetEnumerator();
    }
}

However, it is wise to implement `IEnumerable<>`. Then your type can be used with Linq (extension methods on `IEnumerable<>`), and can be used as argument to other methods that simply require an `IEnumerable<>`.

Also, it is wise to have the method (or explicit interface implementation) that returns the non-generic `IEnumerator` just call through to the method (or explicit interface implementation) that returns `IEnumerator<>`. Having the two return distinct sequences is really confusing (but nice for asking and answering questions on how things work).

Problem

Looking at this code : ``` public class myWords : IEnumerable<string> { string[] f = "I love you".Split(new string[]{"lo"},StringSplitOptions.RemoveEmptyEntries); public IEnumerator<string> GetEnumerator() { return f.Select(s => s + "2").GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return f.Select(s => s + "3").GetEnumerator(); } } ``` Running : ``` myWords m = new myWords(); foreach (var s in m) { Console.WriteLine(s); } ``` Yields ``` I 2 ve you2 // notice "2", so the generic Ienumerator has executed. ``` I understand that the non-generic `IEnumerator` version is for compatibility. Question: - In what scenario will the non-generic be invoked? - How can I force my code to be run with the non-generic `IEnumerator`?

Original source