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.