It’s possible to provide multiple generic enumerators for a single class.  The trick is that clients must specify which enumerator to use.

For example, here is a “MyNumbers” class with multiple generic enumerators (in this case, for custom class “MyInt” and integer):

public class MyNumbers 
    : IEnumerable<MyInt>, IEnumerable<int>

To enumerate through the class, you must use a cast to explicitly specify which enumerator to use, as follows:

foreach (MyInt mi in (IEnumerable<MyInt>)numbers)
{
    // do stuff
}

Note that if you don’t explicitly specify the enumerator, the compiler will generate the following error:

foreach statement cannot operate on variables of type ‘MyNumbers’ because it implements multiple instantiations of ‘System.Collections.Generic.IEnumerable<T>’, try casting to a specific interface instantiation

Sample Code

Here is a simple console program that demonstrates multiple enumerators.  For simplicity, I created a List<int> of integers for IEnumerable<int>.GetEnumerator.  A more efficient approach is to create a custom enumerator (topic for a future article).

using System;
using System.Collections;
using System.Collections.Generic;

namespace MultipleEnumeration
{
    class Program
    {
        static void Main( string[] args )
        {
            MyNumbers numbers = new MyNumbers();
            numbers.Add( new MyInt( 4 ) );
            numbers.Add( new MyInt( 8 ) );
            numbers.Add( new MyInt( 15 ) );

            foreach (MyInt mi in (IEnumerable<MyInt>)numbers)
            {
                Console.WriteLine( mi );
            }
            foreach (int i in (IEnumerable<int>)numbers)
            {
                Console.WriteLine( i );
            }
            Console.ReadLine();
        }
    }
    public class MyInt
    {
        public MyInt() {}
        public MyInt( int i )
        {
            this.Value = i;
        }
        public int Value;
        public override string ToString()
        {
            return this.Value.ToString();
        }
    }
    public class MyNumbers 
        : IEnumerable<MyInt>, IEnumerable<int>
    {
        private List<MyInt> m_Numbers = 
            new List<MyInt>();
        public void Add( MyInt i )
        {
            this.m_Numbers.Add( i );
        }
        IEnumerator<MyInt> IEnumerable<MyInt>.GetEnumerator()
        {
            return this.m_Numbers.GetEnumerator();
        }
        IEnumerator<int> IEnumerable<int>.GetEnumerator()
        {
            List<int> ints = new List<int>();
            for (int i = 0; i < this.m_Numbers.Count; i++)
            {
                ints.Add( this.m_Numbers[i].Value );
            }
            return ints.GetEnumerator();
        }
        IEnumerator IEnumerable.GetEnumerator()
        {
            return this.m_Numbers.GetEnumerator();
        }
    }
}

Share and Enjoy:
  • Digg
  • Twitter
  • Facebook
  • Reddit
  • StumbleUpon
  • LinkedIn
  • Google Bookmarks
  • Slashdot