最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

C#中泛型容器Stack<T>的用法并實(shí)現(xiàn)”撤銷/重做”功能

 更新時(shí)間:2022年10月22日 14:43:04   作者:Darren Ji  
這篇文章介紹了C#中泛型容器Stack<T>的用法并實(shí)現(xiàn)”撤銷/重做”功能,文中通過示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下

.Net為我們提供了眾多的泛型集合。比如,Stack<T>先進(jìn)后出,Queue<T>先進(jìn)先出,List<T>集合元素可排序,支持索引,LinkedList<T>,雙向鏈表的泛型實(shí)現(xiàn),不支持索引;ISet<T>不允許被復(fù)制,他有2個(gè)實(shí)現(xiàn),一個(gè)是HashSet<T>,不維持集合元素的排序,另一個(gè)是SortedSet<T>,支持集合元素的排序;IDictionary<TKey, TValue>是一個(gè)字典集合的泛型接口,SortedList<TKey,TValue>實(shí)現(xiàn)了IDictionary<TKey, TValue>,但同時(shí)也是集合,維持集合元素的排序,支持按鍵或按值索引。

本篇體驗(yàn)Stack<T>的用法。

基本用法

Stack<T>是Stack的泛型實(shí)現(xiàn),提供了若干方法和屬性,比如入棧、出棧、查看棧頂元素,查看棧內(nèi)集合元素?cái)?shù)量,等等。棧的最大特點(diǎn)是先進(jìn)后出,可以把棧想像成一堆疊起來的盤子,入棧就是把一個(gè)個(gè)盤子放到最上面,出棧就是從最上面把盤子拿掉。用法比較簡單:

    class Program
    {
        static void Main(string[] args)
        {
            var customer1 = new Customer() {ID = 1, Name = "張三", Gender = "男"};
            var customer2 = new Customer() { ID = 2, Name = "李四", Gender = "男" };
            Stack<Customer> stackCustomers = new Stack<Customer>();
            //入棧
            stackCustomers.Push(customer1);
            stackCustomers.Push(customer2);
            //查看棧頂元素
            Customer topCustomer = stackCustomers.Peek();
            Console.WriteLine("棧頂元素是:" + topCustomer.Name);
            //遍歷所有棧內(nèi)元素
            foreach (var customer in stackCustomers)
            {
                Console.WriteLine("id is {0},name is {1}", customer.ID, customer.Name);
            }
            //出棧
            Customer outCustomer = stackCustomers.Pop();
            Console.WriteLine("正在出棧的是:" + outCustomer.Name);
            Console.WriteLine("當(dāng)前棧內(nèi)元素?cái)?shù)量為:" + stackCustomers.Count);
            Console.ReadKey();
        }
    }
    public class Customer
    {
        public int ID { get; set; }
        public string Name { get; set; }
        public string Gender { get; set; }
    }

臨摹一個(gè)泛型Stack<T> 

泛型Stack類內(nèi)部維護(hù)這一個(gè)泛型數(shù)組和索引指針,且指針的初始位置是-1。

入棧就是把指針往前提一位,并把入棧元素賦值給該棧內(nèi)位置。另外,入棧要考慮是否達(dá)到容量上限,如果達(dá)到就要給數(shù)組擴(kuò)容。

出棧就是讓當(dāng)前棧位置的元素值為入棧類型的默認(rèn)值,并大指針后退一位。

獲取棧頂元素就是獲取棧當(dāng)前索引位置對(duì)應(yīng)的元素。

    public class MyStack<T>
    {
        //維護(hù)T類型的數(shù)組
        private T[] _elements;
        protected T[] Elements
        {
            get { return _elements; }
            set { _elements = value; }
        }
        public MyStack()
        {
            _capacity = 5;//初始值
            Elements = new T[Capacity];
        }
        public MyStack(int capacity)
        {
            Capacity = capacity;
            Elements = new T[Capacity];
        }
        //指針
        private int _index = -1;
        public int Index
        {
            get { return _index; }
            set { _index = value; }
        }
        //容量
        private int _capacity;
        public int Capacity
        {
            get { return _capacity; }
            set { _capacity = value; }
        }
        //長度=索引+1
        public int Length
        {
            get { return Index + 1; }
        }
        //入棧
        public void Push(T element)
        {
            if (this.Length == Capacity)
            {
                IncreaseCapacity();
            }
            Index++;
            Elements[Index] = element;
        }
        //出棧
        public T Pop()
        {
            if (this.Length < 1)
            {
                throw new InvalidOperationException("棧內(nèi)已空");
            }
            T element = Elements[Index];
            //原先位置元素變成默認(rèn)值
            Elements[Index] = default(T);
            //索引減一
            Index--;
            return element;
        }
        //獲取棧頂元素
        public T Peek()
        {
            if (this.Length < 1)
            {
                throw new InvalidOperationException("棧內(nèi)已空");
            }
            return Elements[Index];
        }
        private void IncreaseCapacity()
        {
            Capacity++;
            Capacity *= 2;
            //創(chuàng)建新的T類型數(shù)組
            T[] newElements = new T[Capacity];
            //把原先的數(shù)組復(fù)制到新的數(shù)組中來
            Array.Copy(Elements, newElements, Elements.Length);
            Elements = newElements;
        }
    }

現(xiàn)在,在客戶端,實(shí)施一系列的入棧和出棧操作。

        static void Main(string[] args)
        {
           //創(chuàng)建泛型Stack實(shí)例
            MyStack<int> myStack = new MyStack<int>();
            //遍歷10次入棧
            for (int i = 0; i < 10; i++)
            {
                Console.WriteLine(i + "開始入棧");
                myStack.Push(i);
                Console.WriteLine("當(dāng)前棧的長度是:" + myStack.Length);
            }
           
            //遍歷10次出棧
            for (int i = 0; i < 10; i++)
            {
                Console.WriteLine("當(dāng)前出棧的是" + myStack.Peek());
                myStack.Pop();
                Console.WriteLine("當(dāng)前棧的長度是:" + myStack.Length);
            }
            //所有出棧結(jié)束,再查看棧頂元素拋異常
            try
            {
                myStack.Peek();
            }
            catch (InvalidOperationException ex)
            {
                Console.WriteLine(ex.Message);
            }
            //所有出棧結(jié)束,再出棧拋異常
            try
            {
                myStack.Pop();
            }
            catch (InvalidOperationException ex)
            {
                Console.WriteLine(ex.Message);
            }
            Console.ReadKey();
        }

其實(shí),泛型Stack<T>的內(nèi)部也是維護(hù)著一個(gè)數(shù)組,數(shù)組的容量是動(dòng)態(tài)變化的,這一點(diǎn)很像List<T>,就像這里提到的。

使用泛型Stack<T>實(shí)現(xiàn)"撤銷/重做"操作

首先,操作或撤銷操作是針對(duì)某種類型的撤銷或重做,提煉出一個(gè)接口。

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

假設(shè),這里想實(shí)現(xiàn)對(duì)整型數(shù)的"撤銷/重做"操作。

    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;
        }
        //執(zhí)行操作
        public int Do(int input)
        {
            return input + _value;
        }
        //撤銷操作
        public int Undo(int input)
        {
            return input - _value;
        }
    }

接下來,需要一個(gè)泛型類來管理所有撤銷或操作命令,把這些命令放在Stack<ICommand<T>>泛型集合中。

    //使用泛型Stack實(shí)現(xiàn)撤銷或重做
    public class UndoRedoStack<T>
    {
        private Stack<ICommand<T>> _undo;//有關(guān)撤銷的泛型stack
        private Stack<ICommand<T>> _redo;//有關(guān)重做的泛型stack
        public UndoRedoStack()
        {
            Reset();
        }
        //記錄撤銷的數(shù)量
        public int UndoCount
        {
            get { return _undo.Count; }
        }
        //記錄重做的數(shù)量
        public int RedoCount
        {
            get { return _redo.Count; }
        }
        //恢復(fù)到出廠設(shè)置
        public void Reset()
        {
            _undo = new Stack<ICommand<T>>();
            _redo = new Stack<ICommand<T>>();
        }
        //執(zhí)行操作
        public T Do(ICommand<T> cmd, T input)
        {
            T output = cmd.Do(input);
            //把剛才的命令放入有關(guān)撤銷的stack中
            _undo.Push(cmd);
            //一旦啟動(dòng)一個(gè)新命令,有關(guān)重做的stack清空
            _redo.Clear();
            return output;
        }
        //撤銷操作
        public T Undo(T input)
        {
            if (_undo.Count > 0)
            {
                //出棧
                ICommand<T> cmd = _undo.Pop();
                T output = cmd.Undo(input);
                _redo.Push(cmd);
                return output;
            }
            else
            {
                return input;
            }
        }
        //重做操作
        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;
            }
        }
    }

最后,在客戶端按如下調(diào)用:

        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("第一次計(jì)算的值為:{0}",count);
            //執(zhí)行撤銷操作一次
            count = intCalulator.Undo(count);
            Console.WriteLine("第二次計(jì)算的值為:{0}",count);
            Console.ReadKey();
        }

以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,謝謝大家對(duì)腳本之家的支持。如果你想了解更多相關(guān)內(nèi)容請(qǐng)查看下面相關(guān)鏈接

相關(guān)文章

  • C#泛型集合類型實(shí)現(xiàn)添加和遍歷

    C#泛型集合類型實(shí)現(xiàn)添加和遍歷

    這篇文章介紹了C#泛型集合類型實(shí)現(xiàn)添加和遍歷的方法,文中通過示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-08-08
  • 用C#獲取硬盤序列號(hào),CPU序列號(hào),網(wǎng)卡MAC地址的源碼

    用C#獲取硬盤序列號(hào),CPU序列號(hào),網(wǎng)卡MAC地址的源碼

    用C#獲取硬盤序列號(hào),CPU序列號(hào),網(wǎng)卡MAC地址的源碼...
    2007-03-03
  • vs 中C#項(xiàng)目讀取JSON配置文件的方法

    vs 中C#項(xiàng)目讀取JSON配置文件的方法

    這篇文章主要介紹了vs中 C#項(xiàng)目讀取JSON配置文件的相關(guān)知識(shí),本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-04-04
  • C#如何遍歷Dictionary

    C#如何遍歷Dictionary

    這篇文章主要為大家詳細(xì)介紹了C#遍歷Dictionary的方法,.NET中的Dictionary是鍵/值對(duì)的集合,使用起來比較方便,Dictionary也可以用KeyValuePair來迭代遍歷,感興趣的小伙伴們可以參考一下
    2016-04-04
  • C#實(shí)現(xiàn)繪制面形圖表的方法詳解

    C#實(shí)現(xiàn)繪制面形圖表的方法詳解

    這篇文章主要介紹了C#實(shí)現(xiàn)繪制面形圖表的方法,對(duì)于C#初學(xué)者很好的掌握C#圖形繪制有一定的借鑒價(jià)值,需要的朋友可以參考下
    2014-07-07
  • C#在復(fù)雜多線程環(huán)境下使用讀寫鎖同步寫入文件

    C#在復(fù)雜多線程環(huán)境下使用讀寫鎖同步寫入文件

    這篇文章介紹了C#在復(fù)雜多線程環(huán)境下使用讀寫鎖同步寫入文件的方法,文中通過示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-04-04
  • C#仿QQ實(shí)現(xiàn)簡單的截圖功能

    C#仿QQ實(shí)現(xiàn)簡單的截圖功能

    這篇文章主要為大家詳細(xì)介紹了如何利用C#語言模擬QQ實(shí)現(xiàn)屏幕選擇區(qū)域截圖功能,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以了解一下
    2022-08-08
  • C#?中的"智能枚舉"之如何在枚舉中增加行為(示例代碼)

    C#?中的"智能枚舉"之如何在枚舉中增加行為(示例代碼)

    這篇文章主要介紹了C#?中的“智能枚舉”之如何在枚舉中增加行為(示例代碼),智能枚舉跟設(shè)計(jì)模式的意義一樣,可以幫助您避免重復(fù)的代碼,并提高代碼的可讀性和可維護(hù)性,需要的朋友可以參考下
    2023-05-05
  • c#使用Unity粒子實(shí)現(xiàn)炮塔發(fā)射系統(tǒng)

    c#使用Unity粒子實(shí)現(xiàn)炮塔發(fā)射系統(tǒng)

    Unity自帶粒子發(fā)射器、動(dòng)畫器、渲染器各兩種,利用Unity的粒子系統(tǒng)制作一個(gè)炮塔發(fā)射系統(tǒng),了解粒子系統(tǒng),必須先了解每一個(gè)屬性都代表了什么,之后才能根據(jù)這些原理來調(diào)整出自己滿意的效果
    2022-04-04
  • c++ STL之list對(duì)結(jié)構(gòu)體的增加,刪除,排序等操作詳解

    c++ STL之list對(duì)結(jié)構(gòu)體的增加,刪除,排序等操作詳解

    這篇文章主要介紹了c++ STL之list對(duì)結(jié)構(gòu)體的增加,刪除,排序等操作詳解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2020-12-12

最新評(píng)論

丰原市| 咸宁市| 靖边县| 苍山县| 久治县| 三门峡市| 永寿县| 周至县| 同德县| 顺义区| 青岛市| 贵溪市| 南靖县| 库伦旗| 库尔勒市| 丹凤县| 徐闻县| 沛县| 和林格尔县| 宁远县| 井冈山市| 长治县| 华坪县| 当阳市| 贺兰县| 获嘉县| 黄大仙区| 江门市| 石林| 内黄县| 清水县| 饶阳县| 德化县| 青神县| 温宿县| 瑞安市| 无棣县| 浪卡子县| 博爱县| 深圳市| 平塘县|