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.

No Comments

No comments yet.

RSS feed for comments on this post.

Sorry, the comment form is closed at this time.

Powered by WordPress