Skip to main content
GameDev.net gamedev.net
🔒 Locked

C# Enumerator Help

Started by Opwiz Nov 2, 2004 at 9:22 AM 10 replies 1.5k views
Original Post
Opwiz
Opwiz
I'm new in programming C# and need some help with Enumerators. I want to control the way my collection's (that implements the generic collection interface) enumerator iterates through the elements. E.g. I have a sorted collection of numbers and I want to iterate through all the numbers that are in a certain interval. Any ideas on how to implement this?
www.marklightforunity.com | MarkLight: Markup Extension Framework for Unity
vHaB
vHaB
At a certain interval? Do you mean like every Nth one?

like given: 1,2,3,4,5,6,7,8,9

and N = 2 gives: 2,4,6,8 ?

if so, you can just mod (%) them with N

SOmething like:

if(count % interval == 0) {
//process here
}
else {
//ignore it
}

Opwiz
Opwiz
No that was just an example.. The point is that I want to somehow control how the Enumerator iterates through the collection.
www.marklightforunity.com | MarkLight: Markup Extension Framework for Unity
cmiskow
cmiskow
I am assuming your collection implements ICollection (= generic collection interface?). You can also implement the IEnumerator interface to get control of the enumerator.

Here is a small example:

public class SampleCollection : ICollection, IEnumerator{    /* ICollection members: CopyTo, Count, IsSynchronized, SyncRoot */    public IEnumerator GetEnumerator()  // from IEnumerable (inherited by ICollection)    {        return this;    // return reference to self    }    public object Current   // member of IEnumerator, retrieves current item    {        get        {            if (m_index >= 0 && m_index < m_array.Length)                return m_array[m_index];            else                throw new InvalidOperationException();        }    }    public void Reset()   // member of IEnumerator, used to reset the enumerator    {        m_index = -1;    }    public bool MoveNext()  // member of IEnumerator, handle custom enumeration ordering here    {        if (m_index < m_array.Length)        {            m_index++;            return true;        }        else        {            return false;        }    }    private int[] m_array = {1, 2, 3, 4, 5};    private int m_index = -1;}
Opwiz
Opwiz
I implement System.Collections.Generic.ICollection and implement the function GetEnumerator() that returns a custom enumerator. The question is how do I control this enumerators iteration based on some data specified by the user? E.g. If the collection is a binary tree that contains 100000 sorted elements and I want the elements between 5000-20000. The custom enumerator knows how to retrieve these elements the fastest (since it knows the internal structure of the binary tree). So somehow I want to specify a parameter to the custom enumerator that controls its iteration.. I wonder which is the best way to do this.
www.marklightforunity.com | MarkLight: Markup Extension Framework for Unity
Opwiz
Opwiz
Quote:
I am assuming your collection implements ICollection (= generic collection interface?). You can also implement the IEnumerator interface to get control of the enumerator.
Yes that is an interesting solution. But that will limit me to having one enumeration at a time and having different kinds of enumerators (in binary-tree I might want (depth-first/breadth-first enumerators). There are other reasons for keeping enumerations code seperated from the container such as making the code more readable etc.
www.marklightforunity.com | MarkLight: Markup Extension Framework for Unity
snk_kid
snk_kid
Quote:
Original post by Opwiz
Quote:
I am assuming your collection implements ICollection (= generic collection interface?). You can also implement the IEnumerator interface to get control of the enumerator.
Yes that is an interesting solution. But that will limit me to having one enumeration at a time and having different kinds of enumerators (in binary-tree I might want (depth-first/breadth-first enumerators). There are other reasons for keeping enumerations code seperated from the container such as making the code more readable etc.


The fact to enumerate by definition means to move one-by-one you can't change that, to return a range of values if thats what you mean't then all you can do is have a method of your binary tree but clients that get passed an instance of your binary tree through an interface say ICollection can only access that method by first checking if its the wright type then doing a cast.

To solve your problem of different kinds of traversal schemes, instead of making your binary tree implement IEnumerator have as many inner classes as you wish to support different traversal schemes, GetEnumerator can return a some default one but extra methods of your binary tree gives a choice of different iterators.
Opwiz
Opwiz
I still want the elements one-by-one but only in a certain range (or more generally elements that meet a certain critera set by the user). As I understand it C# iterates through the elements using foreach. I can see one solution to the problem and that is to have a SetEnumeratorOption() method in the collection that sets some enumerator parameters that is then used when constructing the enumerator in the GetEnumerator() method. So if I want depth-first iteration I call collection.SetEnumeratorOption(DepthFirst, range_criteria_or_something) and then call foreach(obj in collection).. Perhaps that is the best way to go? I can't think of any other solution though.
www.marklightforunity.com | MarkLight: Markup Extension Framework for Unity
snk_kid
snk_kid
Quote:
Original post by Opwiz
I still want the elements one-by-one but only in a certain range (or more generally elements that meet a certain critera set by the user). As I understand it C# iterates through the elements using foreach. I can see one solution to the problem and that is to have a SetEnumeratorOption() method in the collection that sets some enumerator parameters that is then used when constructing the enumerator in the GetEnumerator() method. So if I want depth-first iteration I call collection.SetEnumeratorOption(DepthFirst, range_criteria_or_something) and then call foreach(obj in collection).. Perhaps that is the best way to go? I can't think of any other solution though.


that sounds okay to me, just as long as there is always a default one if some one doesn't wont to set it explicitly or forgets to set.

Remeber thou if some method has an argument say of type reference to ICollection then the client can't see that special method for your class any more so this is where a default is also important.
Opwiz
Opwiz
Quote:
To solve your problem of different kinds of traversal schemes, instead of making your binary tree implement IEnumerator have as many inner classes as you wish to support different traversal schemes, GetEnumerator can return a some default one but extra methods of your binary tree gives a choice of different iterators.


I just realized that using a SetEnumeratorOption() method was exactly what you proposed :). I'll try it. Thanks for the help.
www.marklightforunity.com | MarkLight: Markup Extension Framework for Unity
Opwiz
Opwiz
Ok. I can see why a default Enumerator is important.. also it might be a good idea to clear the options set by SetEnumeratorOptions() in the GetEnumerator() method.
www.marklightforunity.com | MarkLight: Markup Extension Framework for Unity
snk_kid
snk_kid
Quote:
Original post by Opwiz
Quote:
To solve your problem of different kinds of traversal schemes, instead of making your binary tree implement IEnumerator have as many inner classes as you wish to support different traversal schemes, GetEnumerator can return a some default one but extra methods of your binary tree gives a choice of different iterators.


I just realized that using a SetEnumeratorOption() method was exactly what you proposed :). I'll try it. Thanks for the help.


You can apply the Strategy pattern (C# example at link) to this instead of craming in different traversal schemes into one class, make your code abit more cleaner & elegant.

might be playing around with c# later so i might post an example.

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.