C # usage of the generic container Stack & lt; T & gt; and The & rdquo; UNDO/Redo & rdquo; function,

Source: Internet
Author: User

C # how to use a generic container Stack <T> and enable the "undo/Redo" function,

 

. Net provides many generic collections for us. For example, Stack <T> comes first, Queue <T> comes first, and List <T> sets can be sorted. Indexes, sorted List <T>, and bidirectional linked List can be implemented in a generic way, indexes are not supported. ISet <T> cannot be copied. It has two implementations: HashSet <T>, which does not maintain the sorting of set elements, and SortedSet <T>, supports sorting of collection elements. IDictionary <TKey, TValue> is a generic interface for dictionary sets. SortedList <TKey, TValue> implements IDictionary <TKey, TValue>, but it is also a set that maintains the sorting of the Set elements and supports keys or value-based indexes.

 

This article describes how to use a Stack <T>.

 

Basic usage

 

Stack <T> is a Stack generic implementation. It provides several methods and attributes, such as the number of elements in the Stack, the number of elements in the Stack, and the number of elements in the Stack. The biggest feature of the stack is that the stack can be imagined as a stacked plate. In the stack, each plate is placed on the top, and the stack is removed from the top. Easy to use:

 

    class Program
    {
        static void Main(string[] args)
        {
Var customer1 = new Customer () {ID = 1, Name = "Zhang San", Gender = "male "};
Var customer2 = new Customer () {ID = 2, Name = "", Gender = "male "};
            Stack<Customer> stackCustomers = new Stack<Customer>();
// Stack entry
            stackCustomers.Push(customer1);
            stackCustomers.Push(customer2);
// View the top element of the stack
            Customer topCustomer = stackCustomers.Peek();
Console. WriteLine ("top stack element:" + topCustomer. Name );
// Traverse all the elements in the stack
            foreach (var customer in stackCustomers)
            {
                Console.WriteLine("id is {0},name is {1}", customer.ID, customer.Name);
            }
// Output Stack
            Customer outCustomer = stackCustomers.Pop();
Console. WriteLine ("the stack is being output:" + outCustomer. Name );
Console. WriteLine ("number of elements in the current stack:" + stackCustomers. Count );
            Console.ReadKey();
        }
    }
    public class Customer
    {
        public int ID { get; set; }
        public string Name { get; set; }
        public string Gender { get; set; }
    }

 

Copy a generic Stack <T>

 

The generic Stack class maintains this generic array and index pointer internally, and the initial position of the pointer is-1.

 

In the stack, the pointer is directed to the premise and the elements in the stack are assigned to the position in the stack. In addition, whether the upper limit of capacity is reached should be considered for the inbound stack. If the upper limit is reached, the array should be resized.

 

The output stack is used to set the element value of the current stack position to the default value of the inbound stack type, and remove a large pointer.

 

Obtaining the top element of the stack is the element corresponding to the current index position of the stack.

 

    public class MyStack<T>
    {
// Maintain the T-type array
        private T[] _elements;
        protected T[] Elements
        {
            get { return _elements; }
            set { _elements = value; }
        }
        public MyStack()
        {
_ Capacity = 5; // Initial Value
            Elements = new T[Capacity];
        }
        public MyStack(int capacity)
        {
            Capacity = capacity;
            Elements = new T[Capacity];
        }
// Pointer
        private int _index = -1;
        public int Index
        {
            get { return _index; }
            set { _index = value; }
        }
// Capacity
        private int _capacity;
        public int Capacity
        {
            get { return _capacity; }
            set { _capacity = value; }
        }
// Length = index + 1
        public int Length
        {
            get { return Index + 1; }
        }
// Stack entry
        public void Push(T element)
        {
            if (this.Length == Capacity)
            {
                IncreaseCapacity();
            }
            Index++;
            Elements[Index] = element;
        }
// Output Stack
        public T Pop()
        {
            if (this.Length < 1)
            {
Throw new InvalidOperationException ("empty in stack ");
            }
            T element = Elements[Index];
// The original position element is changed to the default value
            Elements[Index] = default(T);
// Subtract one from the index
            Index--;
            return element;
        }
// Obtain the top element of the stack
        public T Peek()
        {
            if (this.Length < 1)
            {
Throw new InvalidOperationException ("empty in stack ");
            }
            return Elements[Index];
        }
        private void IncreaseCapacity()
        {
            Capacity++;
            Capacity *= 2;
// Create a new T-type array
            T[] newElements = new T[Capacity];
// Copy the original array to the new array
            Array.Copy(Elements, newElements, Elements.Length);
            Elements = newElements;
        }
    }

 

Now, a series of inbound and outbound operations are performed on the client.

 

        static void Main(string[] args)
        {
// Create a generic Stack instance
            MyStack<int> myStack = new MyStack<int>();
// Traverse the stack for 10 times
            for (int i = 0; i < 10; i++)
            {
Console. WriteLine (I + "starting to stack ");
                myStack.Push(i);
Console. WriteLine ("the current stack Length is:" + myStack. Length );
            }
           
// Traverse the stack 10 times
            for (int i = 0; i < 10; i++)
            {
Console. WriteLine ("current output stack is" + myStack. Peek ());
                myStack.Pop();
Console. WriteLine ("the current stack Length is:" + myStack. Length );
            }
// When all outbound stacks end, check the top element of the stack and throw an exception.
            try
            {
                myStack.Peek();
            }
            catch (InvalidOperationException ex)
            {
                Console.WriteLine(ex.Message);
            }
// End all outbound stacks and then throw an exception
            try
            {
                myStack.Pop();
            }
            catch (InvalidOperationException ex)
            {
                Console.WriteLine(ex.Message);
            }
            Console.ReadKey();
        }

 

In fact, the <T> of the generic Stack also maintains an array, and the array capacity changes dynamically. This is similar to List <T>, as mentioned here.

 

Use a generic Stack <T> to perform the "undo/Redo" Operation

 

First, the operation or undo operation is to extract an interface for certain types of undo or redo operations.

 

    public interface ICommand<T>
    {
        T Do(T input);
        T Undo(T input);
    }

 

Assume that you want to "undo/Redo" an integer.

 

    public class AddIntCommand : ICommand<int>
    {
        private int _value;
        public int Value
        {
            get { return _value; }
            set { _value = value; }
        }
        public AddIntCommand()
        {
            _value = 0;
        }
        public AddIntCommand(int value)
        {
            _value = value;
        }
// Perform the operation
        public int Do(int input)
        {
            return input + _value;
        }
// Cancel the operation
        public int Undo(int input)
        {
            return input - _value;
        }
    }

 

Next, you need a generic class to manage all the undo or operation commands and place these commands in the Stack <ICommand <T> generic collection.

 

// Undo or redo with generic Stack
    public class UndoRedoStack<T>
    {
Private Stack <ICommand <T> _ undo; // undo-related generic stack
Private Stack <ICommand <T> _ redo; // generic stack related to redo
        public UndoRedoStack()
        {
            Reset();
        }
// Number of records revoked
        public int UndoCount
        {
            get { return _undo.Count; }
        }
// Record the number of retries
        public int RedoCount
        {
            get { return _redo.Count; }
        }
// Restore to factory settings
        public void Reset()
        {
            _undo = new Stack<ICommand<T>>();
            _redo = new Stack<ICommand<T>>();
        }
// Perform the operation
        public T Do(ICommand<T> cmd, T input)
        {
            T output = cmd.Do(input);
// Put the command in the Undo stack.
            _undo.Push(cmd);
// Once a new command is started, the redo stack is cleared.
            _redo.Clear();
            return output;
        }
// Cancel the operation
        public T Undo(T input)
        {
            if (_undo.Count > 0)
            {
// Output Stack
                ICommand<T> cmd = _undo.Pop();
                T output = cmd.Undo(input);
                _redo.Push(cmd);
                return output;
            }
            else
            {
                return input;
            }
        }
// Redo the operation
        public T Redo(T input)
        {
            if (_redo.Count > 0)
            {
                ICommand<T> cmd = _redo.Pop();
                T output = cmd.Do(input);
                _undo.Push(cmd);
                return output;
            }
            else
            {
                return input;
            }
        }
    }

 

Finally, call the following command on the client:

 

        static void Main(string[] args)
        {
            UndoRedoStack<int> intCalulator = new UndoRedoStack<int>();
            int count = 0;
            count = intCalulator.Do(new AddIntCommand(10), count);
            count = intCalulator.Do(new AddIntCommand(20), count);
Console. WriteLine ("value calculated for the first time: {0}", count );
// Perform the Undo operation once
            count = intCalulator.Undo(count);
Console. WriteLine ("the second calculation value is {0}", count );
            Console.ReadKey();
        }    


 

References:

Http://brendan.enrick.com/post/Simple-C-Stack-Implementation

Http://www.cambiaresearch.com/articles/82/generic-undoredo-stack-in-csharp

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.