Files
Convention-Unity/Convention/[Runtime]/Convention.Collections.cs
2025-11-20 17:29:16 +08:00

456 lines
14 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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