Framework / Data Structures / Iterators
In This Topic
    Iterators
    In This Topic

    Iteration interfaces are defining the basics of sequential access. NOV distinguishes between forward (the default) and reverse iteration. The iteration interfaces are declared as follows:

    Iteration Interfaces
    Copy Code
    // Represents an interator, which exposes sequential access to a set of items of the specified type
    public interface INIterator<T>
    {
        // Gets the current item. Valid only if MoveNext() returned true prior to getting the current value.
        T Current { get; }
        // Advances the iterator to the next item of the set.
        // Returns true if the iterator was successfully advanced to the next item.
        // Returns false if the iterator has passed the end of the set.
        bool MoveNext();
        // Resets the iterator to its initial position, which is before the first item in the set.
        void Reset();
    } 
    // Implemented by objects that can provide forward iterators (i.e. support sequential access in first-to-last order).
    public interface INIterable<T>
    {
        // Gets an iterator that iterates through the items in forward order.
        INIterator<T> GetIterator();
    }
    // Implemented by objects that can provide reverse iterators (i.e. support sequential access in last-to-first order).
    public interface INReverseIterable<T>
    {
        // Gets an iterator that iterates through the items in a reverse order.
        INIterator<T> GetReverseIterator();
    }
    

    Typically, you will iterate through the items provided by an iterator by using the following pattern: 

    Iteration Pattern
    Copy Code
    INIterator<T> it = ...; // get an iterator
    while (it.MoveNext())
    {
        T cur = it.Current;
        // do something with current
    }
    

    By design the INSet<T> interface derives from the INIterable<T>, which means that you can get an iterator from all types of sets. That is also why in most cases you will not directly create objects that implement the INIterator<T> interface, but rather get an INIterator<T> interface implementation and use it, as shown in the Iteration Pattern sample.

    Iteration through NOV Data Structures is generally unsafe. This means that it is a developers' responsibility to ensure that the Set from which the iterator was obtained does not mutate during the iteration.

    An important concept in iteration is chaining. Chaining basically allows you to construct a pipeline of iterators so that that the outermost iterator output is subject to specific constrains and the pipeline input is provided by the innermost iterator. An important role in iterators chaining plays the NFilterIterator<T>, that filters the output of another iterator, as demonstrated by the following example:

    Iterators Chaining
    Copy Code
    void ChainIteratorsTest()
    {
        NList<int> values = new NList<int>();
        values.Add(2);
        values.Add(12);
        values.Add(20);
        values.Add(32);
        values.Add(40);
        values.Add(42);
        values.Add(56);
        // create a filter that passes only values in the (20:40) range
        INFilter<int> filter = new NAndFilter<int>(new NGreaterThanFilter<int>(20), new NLessThanFilter<int>(40));
        // filter the values list using above filter
        NFilterIterator<int> filterIt = new NFilterIterator<int>(values.GetIterator(), filter);
        while (filterIt.MoveNext())
        {
            Console.WriteLine(filterIt.Current);
        }
        // output is 32
    }
    

    NOV also implements other interesting iterators, that are summarized by the following table:

    Iterator Description Example
    NEmptyIterator<T>.Instance A singleton empty iterator (an iterator that is always at the end)
    Empty Iterator Sample
    Copy Code
    INIterator<string> it = NEmptyIterator<string>.Instance;
    while (it.MoveNext())
    {
        throw new Exception("I am an exception that will never be thrown");
    }
    
    NSnapshotIterator<T> An iterator that makes an internal copy of the items of another set or iterator, so that it can later serve them.
    NSnapshotIterator<T> Sample
    Copy Code
    NList<string> list = new NList<string>();
    list.Add("NOV");
        
    NSnapshotIterator<string> it = new NSnapshotIterator<string>(list);
    list.Clear();
    while (it.MoveNext())
    {
        Console.Write(it.Current);
    }
    // output is: NOV
    

    Range Iterators

    NArrayIterator<T> An iterator that iterates through all or only a range of items from a specific array.
    NArrayIterator<T> Sample
    Copy Code
    NArrayIterator<string> it = new NArrayIterator<string>(new string[] { "Hello", "NOV", "World" }, 1, 2);
    while (it.MoveNext())
    {
        Console.Write(it.Current);
    }
    // output is: NOVWorld
    
    NArrayReverseIterator<T> An iterator that iterates in reverse order through all or only a range of items from a specific array .
    NArrayReverseIterator<T> Sample
    Copy Code
    NArrayReverseIterator<string> it = new NArrayReverseIterator<string>(new string[] { "Hello", "NOV", "World" }, 1, 2);
    while (it.MoveNext())
    {
        Console.Write(it.Current);
    }
    // output is: WorldNOV
    
    NIndexedSetIterator<T> Same as NArrayIterator<T>, but takes as input an indexed set.
    NIndexedSetReverseIterator<T> Same as NArrayReverseIterator<T>, but takes as input an indexed set.