Saturday, June 20, 2026

C# Example of class that Implements generic IEnumerable interface

Example of a class that Implements generic IEnumerable<T> interface

STEP1. Create MyCollection<T> generic class which implements generic IEnumerable<T>. The IEnumerable<T> in turn inherits non-generic IEnumerable.
using System.Collections;
public class MyCollection<T> : IEnumerable<T>
{
    private T[] _items;
    public MyCollection(T[] items)
    {
        _items = items;
    }

    // The strongly-typed generic method is public
    public IEnumerator<T> GetEnumerator()
    {
        return new MyEnumerator<T>(_items);
    }

    // The legacy non-generic method required by inheritance is private
    IEnumerator IEnumerable.GetEnumerator()
    {
        return this.GetEnumerator();
    }
}
STEP2. MyEnumerator<T> generic class implements generic IEnumerator<T> which in turn inherits non-generic IEnumerator.
public class MyEnumerator<T> : IEnumerator<T>
{
    private T[] _items;
    private int _position = -1;

    public MyEnumerator(T[] items)
    {
        _items = items;
    }

    // Generic Current is a public, standard property
    public T Current
    {
        get
        {
            if (_position < 0 || _position >= _items.Length)
            {
                throw new InvalidOperationException("Enumeration has either not started or has already finished.");
            }
            return _items[_position];
        }
    }

    // Legacy non-generic Current implemented explicitly is private
    object IEnumerator.Current => this.Current;

    // Dispose cannot throw NotImplementedException, as foreach automatically calls it
    public void Dispose()
    {
        // Nothing to clean up for a simple array, so we leave it empty.
    }

    // MoveNext should be public, not explicit
    public bool MoveNext()
    {
        _position++;
        return _position < _items.Length;
    }

    // Reset should be public, not explicit
    public void Reset()
    {
        _position = -1;
    }
}
STEP3. Program class consumes MyCollection<T> class.
public class Program
{
    static void Main(string[] args)
    {
        string[] colors = { "red", "green", "blue", "pink" };
        MyCollection<string> mycollection = new MyCollection<string>(colors);
        IEnumerator<string> enumerator = mycollection.GetEnumerator();
        while (enumerator.MoveNext())
        {
            Console.WriteLine(enumerator.Current);
        }
    }
}
OUTPUT
red
green
blue
pink

In above example, note the explicit interface implementation for the legacy version. Why?

Because IEnumerable<T> inherits from IEnumerable, any class implementing the generic version must implement both GetEnumerator() methods. To avoid a name clash, C# developers use explicit interface implementation for the legacy version.

public class MyCollection<T> : IEnumerable<T>
{
    // The modern, strongly-typed generic method
    public IEnumerator<T> GetEnumerator()
    {
        // Return your generic enumerator here
    }

    // The legacy non-generic method required by inheritance
    // It hides behind the interface to avoid cluttering your class API
    IEnumerator IEnumerable.GetEnumerator()
    {
        // Simply call the generic version above
        return this.GetEnumerator();
    }
}

Note

  • The legacy non generic property and methods are private and explicit interface implementation.
  • The generic property and methods are public and implicit interface implementation.
  • It is required to implement both generic and non generic interfaces, IEnumerable, IEnumerable<T>, IEnumerator, and IEnumerator<T>.

No comments:

Post a Comment

Hot Topics