Jason Bock

Home Biography Speaking Articles Books Music

Multiple Enumerators

I just ran into a situation where I had a class that needed to expose multiple enumerators. However, you can only have one GetEnumerator() method on your class, so … here’s how I got around that.

Here’s the standard, simple example:

internal sealed class SingleDataProducer
{
  public IEnumerator<string> GetEnumerator()
  {
    yield return "one";
    yield return "two";
    yield return "three";
  }
}

But what if I want to have an int and a string enumeration? Well, I can solve that by having two nested classes:

internal sealed class MultipleDataProducer
{
  private List<int> intData = new List<int>(new int[] { 1, 2, 3 });
  private List<string> stringData = new List<string>(new string[] { "one", "two", "three" });

  internal IEnumerable<string> GetStringEnumerator()
  {
    return new StringEnumerator(this);
  }

  internal IEnumerable<int> GetIntEnumerator()
  {
    return new IntEnumerator(this);
  }

  private sealed class IntEnumerator : IEnumerable<int>
  {
    private MultipleDataProducer producer;

    internal IntEnumerator(MultipleDataProducer producer)
      : base()
    {
      this.producer = producer;
    }

    public IEnumerator<int> GetEnumerator()
    {
      foreach(int i in this.producer.intData)
      {
        yield return i;
      }
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
      return this.GetEnumerator();
    }
  }

  private sealed class StringEnumerator : IEnumerable<string>
  {
    private MultipleDataProducer producer;

    internal StringEnumerator(MultipleDataProducer producer)
      : base()
    {
      this.producer = producer;
    }
        
    public IEnumerator<string> GetEnumerator()
    {
      foreach(string s in this.producer.stringData)
      {
        yield return s;
      }
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
      return this.GetEnumerator();
    }
  }
}

By using a nested class that implements IEnumerable<>, I can have the containing class return an instance of the nested class and let it produce the enumeration. When I run the following console application:

class Program
{
  static void Main(string[] args)
  {
    Program.ShowSingleDataProducer();
    Console.Out.WriteLine();
    Program.ShowMultipleDataProducer();
  }

  private static void ShowMultipleDataProducer()
  {
    Console.Out.WriteLine("Multiple Producer");

    MultipleDataProducer producer = new MultipleDataProducer();
        
    foreach(string s in producer.GetStringEnumerator())
    {
      Console.Out.WriteLine(s);            
    }

    foreach(int i in producer.GetIntEnumerator())
    {
      Console.Out.WriteLine(i.ToString());
    }
  }
    
  private static void ShowSingleDataProducer()
  {
    Console.Out.WriteLine("Single Producer");
        
    SingleDataProducer producer = new SingleDataProducer();
        
    foreach(string s in producer)
    {
      Console.Out.WriteLine(s);
    }
  }
}

I get these results:

Single Producer
one
two
three

Multiple Producer
one
two
three
1
2
3

Now, I’m not saying this result is pretty. Something about it seems too complex to me. But … it gets the job done. I’m open to solutions that are more elegant!

Published: 10.09.2007 08:21:37 AM CST