Brewsterware

November 12, 2019

Creating and testing a strongly typed Stack class in X++

Filed under: 365 for Finance and Operations — Joe Brewer @ 12:47 pm

For my latest project in X++ I needed to use a Stack. .NET does already provide a Stack class however MS recommends using the Generics version as it is faster because it is typed. See Non-generic collections shouldn’t be used on GitHub. I had initially tried creating a Stack class using a container, but it was painfully slow – it took several minutes to push and pop 100,000 elements onto and off of the stack.

Here is my implementation:

class Stack extends List
{
    private Types dataType;

    public void push(anytype _value)
    {
        // double check that we have received a variable of the correct type
        if (typeOf(_value) != dataType)
        {
            throw error("Incorrect data type");
        }

        this.addStart(_value);
    }

    public void new(Types _type)
    {
        dataType = _type;

        super(_type);
    }

    public anytype pop()
    {
        ListIterator iterator;
        anytype topValue;

        // double check that there is an element on the stack
        if (!this.elements())
        {
            return null;
        }

        iterator = new ListIterator(this);

        // position the iterator to the top
        iterator.more();

        // retreive the value
        topValue = iterator.value();

        // remove the element from the stack
        iterator.delete();

        // return the value
        return topValue;
    }
}

Here is a job to demonstrate how to use the class and to test the speed of pushing and popping 100,000 elements on to and off of the stack:

class StackTest
{        
    /// <summary>
    /// Runs the class with the specified arguments.
    /// </summary>
    /// <param name = "_args">The specified arguments.</param>
    public static void main(Args _args)
    {    
        System.Random random;
        System.Diagnostics.Stopwatch stopwatch;
        System.TimeSpan timeSpan;
        Stack numberStack;
        str elapsedTime;

        random = new System.Random();
        numberStack = new GWStack(Types::Integer);
        stopwatch = new System.Diagnostics.Stopwatch();

        stopwatch.Start();

        // push 100,000 random numbers onto the stack
        for (int i = 0 ; i <= 100000 ; i++)
        {
            numberStack.push(random.Next(1, 1000));
        }

        // pop everything off of the stack one by one
        for (int i = 0 ; i <= 100000 ; i++)
        {
            numberStack.pop();
        }

        stopwatch.Stop();
        timeSpan = stopwatch.Elapsed;

        elapsedTime = System.String::Format("{0:00}:{1:00}:{2:00}.{3:0000}",
            timeSpan.Hours, timeSpan.Minutes, timeSpan.Seconds,
            timeSpan.Milliseconds);

        info(strFmt("elapsed time for list based stack: %1", elapsedTime));
    }

}

The results show that pushing and popping 100,000 elements is well under 1 second.

Let me know if you use it or if you found this helpful.

Powered by WordPress