FixedSizeStack.cs 4.8 KB
using OnlineStore.Common;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace OnlineStore.DeviceLibrary.deviceLibrary
{
    /// <summary>
    /// 一个固定大小的堆栈。当元素数量超过容量时,最老的元素(栈底)会被自动移除。
    /// </summary>
    /// <typeparam name="T">堆栈中元素的类型</typeparam>
    public class FixedSizeStack<T> : IEnumerable<T>
    {
        private readonly List<T> _internalList = new List<T>();
        private readonly int _capacity;

        /// <summary>
        /// 获取堆栈的最大容量。
        /// </summary>
        public int Capacity => _capacity;

        /// <summary>
        /// 获取当前堆栈中的元素数量。
        /// </summary>
        public int Count => _internalList.Count;

        /// <summary>
        /// 初始化一个新的、指定容量的 FixedSizeStack 实例。
        /// </summary>
        /// <param name="capacity">堆栈的最大容量。</param>
        /// <exception cref="ArgumentOutOfRangeException">当容量小于1时抛出。</exception>
        public FixedSizeStack(int capacity)
        {
            if (capacity < 1)
                throw new ArgumentOutOfRangeException(nameof(capacity), "容量必须大于或等于1。");
            _capacity = capacity;
        }

        /// <summary>
        /// 将一个元素推入堆栈顶部。如果堆栈已满,最老的元素将被移除。
        /// </summary>
        /// <param name="item">要推入的元素。</param>
        public void Push(T item)
        {
            _internalList.Add(item);
            // 如果超出容量,移除最前面(最老)的元素
            if (_internalList.Count > _capacity)
            {
                _internalList.RemoveAt(0);
            }
        }

        /// <summary>
        /// 移除并返回堆栈顶部的元素。
        /// </summary>
        /// <returns>堆栈顶部的元素。</returns>
        /// <exception cref="InvalidOperationException">当堆栈为空时抛出。</exception>
        public T Pop()
        {
            if (_internalList.Count == 0)
                throw new InvalidOperationException("堆栈为空,无法执行 Pop 操作。");

            int lastIndex = _internalList.Count - 1;
            T itemToReturn = _internalList[lastIndex];
            _internalList.RemoveAt(lastIndex);
            return itemToReturn;
        }

        /// <summary>
        /// 返回堆栈顶部的元素,但不移除它。
        /// </summary>
        /// <returns>堆栈顶部的元素。</returns>
        /// <exception cref="InvalidOperationException">当堆栈为空时抛出。</exception>
        public T Peek()
        {
            if (_internalList.Count == 0)
                throw new InvalidOperationException("堆栈为空,无法执行 Peek 操作。");

            return _internalList[_internalList.Count - 1];
        }

        public void Remove(string posid)
        {
            try
            {
                if (!string.IsNullOrEmpty(posid))
                {
                    var idx = _internalList.FindIndex(s => posid.Equals(s));
                    if (idx > -1)
                    {
                        _internalList.RemoveAt(idx);
                    }
                }
            }
            catch(Exception ex)
            {
                LogUtil.error($"移除{posid}失败", ex);
            }

        }

        /// <summary>
        /// 从堆栈中移除所有元素。
        /// </summary>
        public void Clear()
        {
            _internalList.Clear();
        }

        /// <summary>
        /// 返回一个循环访问集合的枚举器。枚举顺序是从栈顶到栈底。
        /// </summary>
        /// <returns>一个可用于循环访问集合的 IEnumerator&lt;T&gt;。</returns>
        public IEnumerator<T> GetEnumerator()
        {
            // 从后往前遍历,模拟从栈顶到栈底的顺序
            for (int i = _internalList.Count - 1; i >= 0; i--)
            {
                yield return _internalList[i];
            }
        }

        /// <summary>
        /// 返回一个循环访问集合的枚举器。
        /// </summary>
        /// <returns>一个可用于循环访问集合的 IEnumerator。</returns>
        IEnumerator IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }

        /// <summary>
        /// 返回一个表示当前对象的字符串。
        /// </summary>
        /// <returns>一个表示当前对象的字符串。</returns>
        public override string ToString()
        {
            return $"FixedSizeStack (Capacity: {_capacity}, Count: {_internalList.Count}) [ {string.Join(", ", _internalList)} ]";
        }
    }
}