locked
IEnumerable or IEnumerable<T> RRS feed

  • Question

  • I've created a new generic class (MyClass<T>) and I'm trying to figure out how I implement an enumerator for it. The only examples I can find show you creating another class that implements IEnumerator. While I can easily do the MoveNext, Reset, Current, I don't see how I pass my object to the IEnumerator class since it needs a type for T.

    Ron Whittle - If the post is helpful or answers your question, please mark it as such.
    Wednesday, October 21, 2009 12:50 AM

Answers

  • There are lots of options.  The easiest is to use the yield statement:

    public class MyClass<T> : IEnumerable<T>
    {
        // for option 1
        private List<T> values;
    
        // for option 2
        private T GetValue(int index) { ... }
    
        public IEnumerator<T> GetEnumerator()
        {
            // Option 1: If you have some sort of list...
            foreach(var value in values) // or whatever you're enumerating
            {
                 yield return value;
            }
    
    
            // Option 2:just yield values
            yield return GetValue(0);
            yield return GetValue(1);
            yield return GetValue(2);
            for (int i=5; i<15;++i)
                yield return GetValue(i);
        }
    
        // Handle non-generic
        IEnumerator IEnumerable.GetEnumerator()
        {
            return this.GetEnumerator();
        }
    }
    The other option is to make a custom IEnumerator<T> class.  I usually use a private class:

    public class MyClass<T> : IEnumerable<T>
    {
        // for option 1
        private List<T> values;
    
        // for option 2
        private T GetValue(int index) { ... }
    
        public IEnumerator<T> GetEnumerator()
        {
             return new MyClassEnumerator<T>(this);
        }
      
        // Handle non-generic
        IEnumerator IEnumerable.GetEnumerator()
        {
            return this.GetEnumerator();
        }
    
        private class MyClassEnumerator<T> : IEnumerator<T>
        {
            private MyClass<T> parent;
            public MyClassEnumerator<T>(MyClass<T> parent)
            {
                this.parent = parent;
            }
            // Implement movenext, etc...
        }
    
    }

    Reed Copsey, Jr. - http://reedcopsey.com
    • Marked as answer by Ron.Whittle Wednesday, October 21, 2009 2:02 AM
    Wednesday, October 21, 2009 1:36 AM

All replies

  • There are lots of options.  The easiest is to use the yield statement:

    public class MyClass<T> : IEnumerable<T>
    {
        // for option 1
        private List<T> values;
    
        // for option 2
        private T GetValue(int index) { ... }
    
        public IEnumerator<T> GetEnumerator()
        {
            // Option 1: If you have some sort of list...
            foreach(var value in values) // or whatever you're enumerating
            {
                 yield return value;
            }
    
    
            // Option 2:just yield values
            yield return GetValue(0);
            yield return GetValue(1);
            yield return GetValue(2);
            for (int i=5; i<15;++i)
                yield return GetValue(i);
        }
    
        // Handle non-generic
        IEnumerator IEnumerable.GetEnumerator()
        {
            return this.GetEnumerator();
        }
    }
    The other option is to make a custom IEnumerator<T> class.  I usually use a private class:

    public class MyClass<T> : IEnumerable<T>
    {
        // for option 1
        private List<T> values;
    
        // for option 2
        private T GetValue(int index) { ... }
    
        public IEnumerator<T> GetEnumerator()
        {
             return new MyClassEnumerator<T>(this);
        }
      
        // Handle non-generic
        IEnumerator IEnumerable.GetEnumerator()
        {
            return this.GetEnumerator();
        }
    
        private class MyClassEnumerator<T> : IEnumerator<T>
        {
            private MyClass<T> parent;
            public MyClassEnumerator<T>(MyClass<T> parent)
            {
                this.parent = parent;
            }
            // Implement movenext, etc...
        }
    
    }

    Reed Copsey, Jr. - http://reedcopsey.com
    • Marked as answer by Ron.Whittle Wednesday, October 21, 2009 2:02 AM
    Wednesday, October 21, 2009 1:36 AM
  • Thanks, your second example was what I was about to try :)

    Ron Whittle - If the post is helpful or answers your question, please mark it as such.
    Wednesday, October 21, 2009 2:03 AM