.Net为我们提供了众多的泛型集合。比如,Stack
本篇体验Stack
基本用法
Stack
class Program { static void Main(string[] args) { var customer1 = new Customer() {ID = 1, Name = "张三", Gender = "男"}; var customer2 = new Customer() { ID = 2, Name = "李四", Gender = "男" }; StackstackCustomers = new Stack (); //入栈 stackCustomers.Push(customer1); stackCustomers.Push(customer2); //查看栈顶元素 Customer topCustomer = stackCustomers.Peek(); Console.WriteLine("栈顶元素是:" + topCustomer.Name); //遍历所有栈内元素 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("当前栈内元素数量为:" + stackCustomers.Count); Console.ReadKey(); } } public class Customer { public int ID { get; set; } public string Name { get; set; } public string Gender { get; set; } }
临摹一个泛型Stack
泛型Stack类内部维护这一个泛型数组和索引指针,且指针的初始位置是-1。
入栈就是把指针往前提一位,并把入栈元素赋值给该栈内位置。另外,入栈要考虑是否达到容量上限,如果达到就要给数组扩容。
出栈就是让当前栈位置的元素值为入栈类型的默认值,并大指针后退一位。
获取栈顶元素就是获取栈当前索引位置对应的元素。
public class MyStack{ //维护T类型的数组 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("栈内已空"); } T element = Elements[Index]; //原先位置元素变成默认值 Elements[Index] = default(T); //索引减一 Index--; return element; } //获取栈顶元素 public T Peek() { if (this.Length < 1) { throw new InvalidOperationException("栈内已空"); } return Elements[Index]; } private void IncreaseCapacity() { Capacity++; Capacity *= 2; //创建新的T类型数组 T[] newElements = new T[Capacity]; //把原先的数组复制到新的数组中来 Array.Copy(Elements, newElements, Elements.Length); Elements = newElements; } }
现在,在客户端,实施一系列的入栈和出栈操作。
static void Main(string[] args) { //创建泛型Stack实例 MyStackmyStack = new MyStack (); //遍历10次入栈 for (int i = 0; i < 10; i++) { Console.WriteLine(i + "开始入栈"); myStack.Push(i); Console.WriteLine("当前栈的长度是:" + myStack.Length); } //遍历10次出栈 for (int i = 0; i < 10; i++) { Console.WriteLine("当前出栈的是" + myStack.Peek()); myStack.Pop(); Console.WriteLine("当前栈的长度是:" + myStack.Length); } //所有出栈结束,再查看栈顶元素抛异常 try { myStack.Peek(); } catch (InvalidOperationException ex) { Console.WriteLine(ex.Message); } //所有出栈结束,再出栈抛异常 try { myStack.Pop(); } catch (InvalidOperationException ex) { Console.WriteLine(ex.Message); } Console.ReadKey(); }
其实,泛型Stack
使用泛型Stack
首先,操作或撤销操作是针对某种类型的撤销或重做,提炼出一个接口。
public interface ICommand{ T Do(T input); T Undo(T input); }
假设,这里想实现对整型数的"撤销/重做"操作。
public class AddIntCommand : ICommand{ private int _value; public int Value { get { return _value; } set { _value = value; } } public AddIntCommand() { _value = 0; } public AddIntCommand(int value) { _value = value; } //执行操作 public int Do(int input) { return input + _value; } //撤销操作 public int Undo(int input) { return input - _value; } }
接下来,需要一个泛型类来管理所有撤销或操作命令,把这些命令放在Stack
//使用泛型Stack实现撤销或重做 public class UndoRedoStack{ private Stack > _undo;//有关撤销的泛型stack private Stack > _redo;//有关重做的泛型stack public UndoRedoStack() { Reset(); } //记录撤销的数量 public int UndoCount { get { return _undo.Count; } } //记录重做的数量 public int RedoCount { get { return _redo.Count; } } //恢复到出厂设置 public void Reset() { _undo = new Stack >(); _redo = new Stack >(); } //执行操作 public T Do(ICommand cmd, T input) { T output = cmd.Do(input); //把刚才的命令放入有关撤销的stack中 _undo.Push(cmd); //一旦启动一个新命令,有关重做的stack清空 _redo.Clear(); return output; } //撤销操作 public T Undo(T input) { if (_undo.Count > 0) { //出栈 ICommand 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 cmd = _redo.Pop(); T output = cmd.Do(input); _undo.Push(cmd); return output; } else { return input; } } }
最后,在客户端按如下调用:
static void Main(string[] args) { UndoRedoStackintCalulator = new UndoRedoStack (); int count = 0; count = intCalulator.Do(new AddIntCommand(10), count); count = intCalulator.Do(new AddIntCommand(20), count); Console.WriteLine("第一次计算的值为:{0}",count); //执行撤销操作一次 count = intCalulator.Undo(count); Console.WriteLine("第二次计算的值为:{0}",count); Console.ReadKey(); }
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对脚本之家的支持。如果你想了解更多相关内容请查看下面相关链接