riki
riki

Reputation: 2393

Why implementation of IEnumerable not require when iterate using foreach

I was looking into the IEnumerable and trying the example given in this link. I understand that when we iterate using foreach the GetEnumerator() method gets call because my List class has implemented IEnumerable (or may be I am wrong).

   public class List<T> : IEnumerable
    {
        private T[] _collection;
        public List(T[] inputs)
        {
            _collection = new T[inputs.Length];
            for (int i = 0; i < inputs.Length; i++)
            {
                _collection[i] = inputs[i];
            }
        }
        IEnumerator IEnumerable.GetEnumerator()
        {
            return (IEnumerator)GetEnumerator();
        }
        public CollectionEnum<T> GetEnumerator()
        {
            return new CollectionEnum<T>(_collection);
        }
    }

public class CollectionEnum<T> : IEnumerator
    {
        public T[] _collection ;
        int position = -1;
        public CollectionEnum(T[] list)
        {
            _collection = list;
        }
        public bool MoveNext()
        {
            position++;
            return (position < _collection.Length);
        }
        //implementation on Current and Reset
    }

Then, it is also mentioned that implementation of IEnumerable is not required to iterate using foreach. So, in the above code if I remove the implementation of IEnumerable the foreach must work. So my List<> class looks like

public class List<T>
{
    private T[] _collection;
    public List(T[] persons)
    {
        _collection = new T[persons.Length];
        for (int i = 0; i < persons.Length; i++)
        {
            _collection[i] = persons[i];
        }
    }
    public CollectionEnum<T> GetEnumerator()
    {
        return new CollectionEnum<T>(_collection);
    }
}

And which does work. Now I did not understand how foreach knows my class has a method call GetEnumerator() which returns a IEnumerator type.

Upvotes: 2

Views: 621

Answers (2)

Eniola
Eniola

Reputation: 720

As Nkosi mentions, in interpreting foreach, the compiler looks for a pattern originally represented in IEnumerable and IEnumerator.

Earlier versions of the C# compiler required the implementation of these interfaces. However, with the advent of LINQ, the language and compiler have been adjusted to do more of recognizing patterns.

For instance, you can create a LINQ query around an object that has a Where method but doesn't implement IEnumerable.

Similarly, you can await any object that follows the Awaitable Pattern not just Task or Task.

Once you understand the particular methods the compiler is looking for to satisfy a pattern it becomes easier to wrap your head around why IEnumerable is not required for foreach. Remember also that foreach is really just syntactic sugar for traversing a collection of objects.

Upvotes: 1

Nkosi
Nkosi

Reputation: 247088

The article you linked to provided the explanation to you already in the remarks.

If your collection does not implement IEnumerable, you must still follow the iterator pattern to support this syntax by providing a GetEnumerator method that returns an interface, class or struct....that contains a Current property, and MoveNext and Reset methods as described by IEnumerator, but the class does not have to implement IEnumerator.

Upvotes: 2

Related Questions