using System; using System.Collections; using System.Collections.Generic; using System.Runtime.InteropServices; namespace Convention.Collections { namespace Generic { /// /// 附带有缓存机制的链表类 /// /// 指定链表的元素类型 public sealed class LinkedCacheList : ICollection, IEnumerable, ICollection, IEnumerable { private readonly LinkedList m_LinkedList; /// /// 之所以需要这套缓存机制,主要有三点好处: /// 减少 GC 压力:大量频繁的插入/删除会产生很多短生命周期的节点对象,通过复用可以显著降低托管堆的分配与回收次数 /// 提升性能:避免频繁 new 和 GC,能减少停顿时间,提高链表在高频操作场景下的吞吐 /// 便于观察与管理:类中还提供了 CachedNodeCount 方便调试统计缓存规模,必要时可通过 ClearCachedNodes 主动释放 /// 适用场景是节点使用模式“高频增删但总量有限”,此时缓存能稳定性能;若链表规模始终在增长且很少释放,缓存收益会较低。 /// private readonly Queue> m_CachedNodes; /// /// 初始化游戏框架链表类的新实例 /// public LinkedCacheList() { m_LinkedList = new LinkedList(); m_CachedNodes = new Queue>(); } /// /// 获取链表中实际包含的结点数量 /// public int Count { get { return m_LinkedList.Count; } } /// /// 获取链表结点缓存数量 /// public int CachedNodeCount { get { return m_CachedNodes.Count; } } /// /// 获取链表的第一个结点 /// public LinkedListNode First { get { return m_LinkedList.First; } } /// /// 获取链表的最后一个结点 /// public LinkedListNode Last { get { return m_LinkedList.Last; } } /// /// 获取一个值,该值指示 是否为只读 /// public bool IsReadOnly { get { return ((ICollection)m_LinkedList).IsReadOnly; } } /// /// 获取可用于同步对 的访问的对象。 /// public object SyncRoot { get { return ((ICollection)m_LinkedList).SyncRoot; } } /// /// 获取一个值,该值指示是否同步对 的访问(线程安全)。 /// public bool IsSynchronized { get { return ((ICollection)m_LinkedList).IsSynchronized; } } /// /// 在链表中指定的现有结点后添加包含指定值的新结点 /// /// 指定的现有结点 /// 指定值 /// 包含指定值的新结点 public LinkedListNode AddAfter(LinkedListNode node, T value) { LinkedListNode newNode = AcquireNode(value); m_LinkedList.AddAfter(node, newNode); return newNode; } /// /// 在链表中指定的现有结点后添加指定的新结点 /// /// 指定的现有结点 /// 指定的新结点 public void AddAfter(LinkedListNode node, LinkedListNode newNode) { m_LinkedList.AddAfter(node, newNode); } /// /// 在链表中指定的现有结点前添加包含指定值的新结点 /// /// 指定的现有结点 /// 指定值 /// 包含指定值的新结点 public LinkedListNode AddBefore(LinkedListNode node, T value) { LinkedListNode newNode = AcquireNode(value); m_LinkedList.AddBefore(node, newNode); return newNode; } /// /// 在链表中指定的现有结点前添加指定的新结点 /// /// 指定的现有结点 /// 指定的新结点 public void AddBefore(LinkedListNode node, LinkedListNode newNode) { m_LinkedList.AddBefore(node, newNode); } /// /// 在链表的开头处添加包含指定值的新结点 /// /// 指定值 /// 包含指定值的新结点 public LinkedListNode AddFirst(T value) { LinkedListNode node = AcquireNode(value); m_LinkedList.AddFirst(node); return node; } /// /// 在链表的开头处添加指定的新结点 /// /// 指定的新结点 public void AddFirst(LinkedListNode node) { m_LinkedList.AddFirst(node); } /// /// 在链表的结尾处添加包含指定值的新结点 /// /// 指定值 /// 包含指定值的新结点 public LinkedListNode AddLast(T value) { LinkedListNode node = AcquireNode(value); m_LinkedList.AddLast(node); return node; } /// /// 在链表的结尾处添加指定的新结点 /// /// 指定的新结点 public void AddLast(LinkedListNode node) { m_LinkedList.AddLast(node); } /// /// 从链表中移除所有结点 /// public void Clear() { LinkedListNode current = m_LinkedList.First; while (current != null) { ReleaseNode(current); current = current.Next; } m_LinkedList.Clear(); } /// /// 清除链表结点缓存 /// public void ClearCachedNodes() { m_CachedNodes.Clear(); } /// /// 确定某值是否在链表中 /// /// 指定值 /// 某值是否在链表中 public bool Contains(T value) { return m_LinkedList.Contains(value); } /// /// 从目标数组的指定索引处开始将整个链表复制到兼容的一维数组 /// /// 一维数组,它是从链表复制的元素的目标。数组必须具有从零开始的索引 /// array 中从零开始的索引,从此处开始复制 public void CopyTo(T[] array, int index) { m_LinkedList.CopyTo(array, index); } /// /// 从特定的 ICollection 索引开始,将数组的元素复制到一个数组中 /// /// 一维数组,它是从 ICollection 复制的元素的目标。数组必须具有从零开始的索引 /// array 中从零开始的索引,从此处开始复制 public void CopyTo(Array array, int index) { ((ICollection)m_LinkedList).CopyTo(array, index); } /// /// 查找包含指定值的第一个结点 /// /// 要查找的指定值 /// 包含指定值的第一个结点 public LinkedListNode Find(T value) { return m_LinkedList.Find(value); } /// /// 查找包含指定值的最后一个结点 /// /// 要查找的指定值 /// 包含指定值的最后一个结点 public LinkedListNode FindLast(T value) { return m_LinkedList.FindLast(value); } /// /// 从链表中移除指定值的第一个匹配项 /// /// 指定值 /// 是否移除成功 public bool Remove(T value) { LinkedListNode node = m_LinkedList.Find(value); if (node != null) { m_LinkedList.Remove(node); ReleaseNode(node); return true; } return false; } /// /// 从链表中移除指定的结点 /// /// 指定的结点 public void Remove(LinkedListNode node) { m_LinkedList.Remove(node); ReleaseNode(node); } /// /// 移除位于链表开头处的结点 /// public void RemoveFirst() { LinkedListNode first = m_LinkedList.First; if (first == null) { throw new InvalidOperationException("Rmove first is invalid."); } m_LinkedList.RemoveFirst(); ReleaseNode(first); } /// /// 移除位于链表结尾处的结点。 /// public void RemoveLast() { LinkedListNode last = m_LinkedList.Last; if (last == null) { throw new InvalidOperationException("Remove last is invalid."); } m_LinkedList.RemoveLast(); ReleaseNode(last); } /// /// 返回循环访问集合的枚举数 /// /// 循环访问集合的枚举数 public Enumerator GetEnumerator() { return new Enumerator(m_LinkedList); } private LinkedListNode AcquireNode(T value) { LinkedListNode node = null; if (m_CachedNodes.Count > 0) { node = m_CachedNodes.Dequeue(); node.Value = value; } else { node = new LinkedListNode(value); } return node; } private void ReleaseNode(LinkedListNode node) { node.Value = default(T); m_CachedNodes.Enqueue(node); } /// /// 将值添加到 ICollection`1 的结尾处 /// /// 要添加的值 void ICollection.Add(T value) { AddLast(value); } /// /// 返回循环访问集合的枚举数 /// /// 循环访问集合的枚举数 IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } /// /// 返回循环访问集合的枚举数 /// /// 循环访问集合的枚举数 IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } /// /// 循环访问集合的枚举数 /// [StructLayout(LayoutKind.Auto)] public struct Enumerator : IEnumerator, IEnumerator { private LinkedList.Enumerator m_Enumerator; internal Enumerator(LinkedList linkedList) { if (linkedList == null) { throw new InvalidOperationException("Linked list is invalid."); } m_Enumerator = linkedList.GetEnumerator(); } /// /// 获取当前结点 /// public T Current { get { return m_Enumerator.Current; } } /// /// 获取当前的枚举数 /// object IEnumerator.Current { get { return m_Enumerator.Current; } } /// /// 清理枚举数 /// public void Dispose() { m_Enumerator.Dispose(); } /// /// 获取下一个结点 /// /// 返回下一个结点 public bool MoveNext() { return m_Enumerator.MoveNext(); } /// /// 重置枚举数 /// void IEnumerator.Reset() { ((IEnumerator)m_Enumerator).Reset(); } } } } }