在这里插入图片描述

如果你有以下需求:
1. 需要对Dictionary进行遍历的同时移除或者添加元素
2. 需要按顺序遍历Dictionary并且保证先入先出
3. 需要即时的获取字典内的元素数量,即时增删


如果你觉得好,请给我的框架点一个免费的star,球球啦
Yueh0607 - AirFramework


动态字典实现

/********************************************************************************************
 * Date : 2023.1.30
 * Description : 
 * 可顺序遍历且可以随机移除的队列
 * 
 * 遍历方法例程:
 * 
            _modules.ResetTraversalCount();
            int traversalCount = _modules.TraversalCount;    
            for (int i = 0; i < traversalCount; ++i)
            {
                if (_modules.TryDequeue(out IModule module, out Type key))
                {
                    module.OnUpdate();
                    _modules.TryEnqueue(key, module);
                }
            }
 * 
 * 
 ********************************************************************************************/


using System;
using System.Collections;
using System.Collections.Generic;
namespace AirFramework
{
    public class DynamicDictionary<T, K> : IEnumerable<KeyValuePair<T, K>> where T : notnull
    {

        //队列顺序
        private readonly Queue<T> queue;
        //实际存储键值对,即时
        private readonly Dictionary<T, K> dictionary;
        //临时移除状态
        private readonly Dictionary<T, int> state;

        /// <summary>
        /// 真正剩余元素数量
        /// </summary>
        public int Count => dictionary.Count;

        /// <summary>
        /// 遍历出队的次数
        /// </summary>
        public int TraversalCount { get; private set; } = 0;

        /// <summary>
        /// 刷新遍历数量,在每次遍历之前都要进行一次刷新以校准遍历数量
        /// </summary>
        public int ResetTraversalCount() => TraversalCount = queue.Count;

        public DynamicDictionary()
        {
            queue = new Queue<T>();
            dictionary = new Dictionary<T, K>();
            state = new Dictionary<T, int>();
        }

        /// <summary>
        /// 通过自定义比较器来提高字典比较效率的构造方式
        /// </summary>
        /// <param name="equalityComparer"></param>
        public DynamicDictionary(IEqualityComparer<T> equalityComparer)
        {
            queue = new Queue<T>();
            dictionary = new Dictionary<T, K>(equalityComparer);
            state = new Dictionary<T, int>(equalityComparer);
        }


        /// <summary>
        /// 入队
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value"></param>
        public void Enqueue(T key, K value)
        {
            if (TryEnqueue(key, value)) return;
            throw new InvalidOperationException("The operation on an empty container is invalid");
        }
        /// <summary>
        /// 尝试入队
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public bool TryEnqueue(T key, K value)
        {
            if (!dictionary.TryAdd(key, value))
            {
                return false;
            }
            queue.Enqueue(key);
            return true;
        }
        /// <summary>
        /// 从队中移除
        /// </summary>
        /// <param name="key"></param>
        public void Remove(T key)
        {
            if (!TryRemove(key))
            {
                throw new InvalidOperationException("The operation on an empty container is invalid");
            }
        }
        /// <summary>
        /// 尝试从队中移除
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public bool TryRemove(T key)
        {
            if (dictionary.ContainsKey(key))
            {
                dictionary.Remove(key);
                if (state.ContainsKey(key)) state[key]++;
                else state.Add(key, 1);
                return true;
            }
            return false;
        }

        /// <summary>
        /// 尝试获取队首
        /// </summary>
        /// <param name="result"></param>
        /// <returns></returns>
        public bool TryPeek(out K result)
        {
            do
            {
                if (queue.TryPeek(out var key))
                {
                    if (state.TryGetValue(key, out int count))
                    {
                        state[key] = --count;
                        if (TraversalCount > 0) TraversalCount--;
                        if (count == 0) state.Remove(key);
                        queue.Dequeue();
                    }
                    else return dictionary.TryGetValue(key, out result);
                }
                else
                {
                    result = default;
                    return false;
                }
            }
            while (true);
        }
        /// <summary>
        /// 获取队首
        /// </summary>
        /// <returns></returns>
        /// <exception cref="InvalidOperationException"></exception>
        public K Peek()
        {
            if (TryPeek(out var result)) return result;
            throw new InvalidOperationException("The operation on an empty container is invalid");
        }
        /// <summary>
        /// 尝试出队
        /// </summary>
        /// <param name="result"></param>
        /// <returns></returns>
        public bool TryDequeue(out K result)
        {
            return TryDequeue(out result, out _);
        }
        /// <summary>
        /// 尝试出队
        /// </summary>
        /// <param name="result"></param>
        /// <param name="k"></param>
        /// <returns></returns>
        public bool TryDequeue(out K result, out T k)
        {
            if (queue.TryDequeue(out var key))
            {
                while (state.TryGetValue(key, out var count))
                {
                    state[key] = --count;
                    if (TraversalCount > 0) TraversalCount--;
                    if (count == 0) state.Remove(key);
                    if (!queue.TryDequeue(out key))
                    {
                        result = default;
                        k = default;
                        return false;
                    }
                }
                if (dictionary.TryGetValue(key, out result))
                {
                    k = key;
                    dictionary.Remove(key);
                    return true;
                }
            }

            result = default;
            k = default;
            return false;
        }

        /// <summary>
        /// 出队
        /// </summary>
        /// <returns></returns>
        /// <exception cref="InvalidOperationException"></exception>
        public K Dequeue()
        {
            if (TryDequeue(out var result))
            {
                return result;
            }
            throw new InvalidOperationException("The operation on an empty container is invalid");
        }

        /// <summary>
        /// 访问以K为键的对象
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public K this[T key]
        {
            get => dictionary[key];
            set => dictionary[key] = value;
        }
        /// <summary>
        /// 是否存在以K为键的对象
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public bool ContainsKey(T key) => dictionary.ContainsKey(key);

        /// <summary>
        /// 清空
        /// </summary>
        public void Clear()
        {
            dictionary.Clear();
            queue.Clear();
            state.Clear();
        }


        /// <summary>
        /// 无序遍历  不可动态随机移除  迭代器
        /// </summary>
        /// <returns></returns>
        public IEnumerator<KeyValuePair<T, K>> GetEnumerator()
        {
            return dictionary.GetEnumerator();
        }

        IEnumerator IEnumerable.GetEnumerator()
        {
            return dictionary.GetEnumerator();
        }
    }
}

配套拓展方法

using System;
namespace AirFramework
{
    public static class DynamicDictionaryExtensions
    {
        /// <summary>
        /// 从动态字典获取一个值,如果值不存在则返回传入的默认值
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <typeparam name="K"></typeparam>
        /// <param name="dictionary"></param>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public static K GetValueOrDefault<T, K>(this DynamicDictionary<T, K> dictionary, T key, K value = default)
        {
            if (dictionary.ContainsKey(key))
            {
                return dictionary[key];
            }
            return value;

        }
        /// <summary>
        /// 从动态字典获取一个值,如果不存在则添加指定值后返回该值
        /// </summary>
        /// <typeparam name="T">键类型</typeparam>
        /// <typeparam name="K">值类型</typeparam>
        /// <param name="dictionary">动态字典</param>
        /// <param name="key">键</param>
        /// <param name="value">默认值</param>
        /// <returns>值</returns>
        public static K GetValueOrAddDefault<T, K>(this DynamicDictionary<T, K> dictionary, T key, K value = default)
        {
            if (dictionary.ContainsKey(key))
            {
                return dictionary[key];
            }
            dictionary.Enqueue(key, value);
            return dictionary[key];
        }
        /// <summary>
        /// 从动态字典获取一个值,如果不存在则添加指定值后返回该值
        /// </summary>
        /// <typeparam name="T">键类型</typeparam>
        /// <typeparam name="K">值类型</typeparam>
        /// <param name="dictionary">动态字典</param>
        /// <param name="key">键</param>
        /// <param name="value">默认值</param>
        /// <returns>值</returns>
        public static K GetValueOrAddDefault<T, K>(this DynamicDictionary<T, K> dictionary, T key, Func<K> getter = null)
        {
            if (dictionary.ContainsKey(key))
            {
                return dictionary[key];
            }

            dictionary.Enqueue(key, getter == null ? default : getter());
            return dictionary[key];
        }

        /// <summary>
        /// 尝试从动态字典获取一个值,如果该值存在则返回true并传出Value
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <typeparam name="K"></typeparam>
        /// <param name="dictionary"></param>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public static bool TryGetValue<T, K>(this DynamicDictionary<T, K> dictionary, T key, out K value)
        {
            if (dictionary.ContainsKey(key))
            {
                value = dictionary[key];
                return true;
            }
            value = default;
            return false;
        }

        /// <summary>
        /// 尝试从动态字典获取一个值,如果该值存在则返回true并传出Value
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <typeparam name="K"></typeparam>
        /// <param name="dictionary"></param>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public static bool GetValueOrDefault<T, K>(this DynamicDictionary<T, K> dictionary, T key, out K value)
        {
            if (dictionary.ContainsKey(key))
            {
                value = dictionary[key];
                return true;
            }
            value = default;
            return false;
        }


        /// <summary>
        /// 尝试从动态字典移除一个值并调用Dispose,如果该值存在则返回true
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <typeparam name="K"></typeparam>
        /// <param name="dictionary"></param>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public static bool TryRemoveAndDispose<T, K>(this DynamicDictionary<T, K> dictionary, T key) where K : IDisposable
        {
            if (dictionary.TryGetValue(key, out var value))
            {
                value.Dispose();
                return true;
            }
            return false;
        }

        /// <summary>
        /// 从动态字典移除一个值并调用其Dispose方法,如果该值不存在将引发异常
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <typeparam name="K"></typeparam>
        /// <param name="dictionary"></param>
        /// <param name="key"></param>
        public static void RemoveAndDispose<T, K>(this DynamicDictionary<T, K> dictionary, T key) where K : IDisposable
        {
            dictionary.Remove(key);
            dictionary[key].Dispose();
        }

        /// <summary>
        /// 清空动态字典并调用所有元素的Dispose方法s
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <typeparam name="K"></typeparam>
        /// <param name="dictionary"></param>
        public static void ClearAndDispose<T, K>(this DynamicDictionary<T, K> dictionary) where K : IDisposable
        {
            while (dictionary.Count > 0)
            {
                dictionary.Dequeue().Dispose();
            }
        }
    }
}

动态HashSet的实现

/********************************************************************************************
 * Date : 2023.1.30
 * Description : 
 * 可顺序遍历且可以随机移除的队列
 * 
 * 遍历方法例程:
 * 
            _modules.ResetTraversalCount();
            int traversalCount = _modules.TraversalCount;    
            for (int i = 0; i < traversalCount; ++i)
            {
                if (_modules.TryDequeue(out IModule module))
                {
                    module.OnUpdate();
                    _modules.TryEnqueue( module);
                }
            }
 * 
 * 
 ********************************************************************************************/


using System;
using System.Collections;
using System.Collections.Generic;
namespace AirFramework
{
    public class DynamicHashSet<T> : IEnumerable<T> where T : notnull
    {

        //队列顺序
        private readonly Queue<T> queue;
        //实际存储键值对,即时
        private readonly HashSet<T> hashSet;
        //临时移除状态
        private readonly Dictionary<T, int> state;

        /// <summary>
        /// 真正剩余元素数量
        /// </summary>
        public int Count => hashSet.Count;

        /// <summary>
        /// 遍历出队的次数
        /// </summary>
        public int TraversalCount { get; private set; } = 0;

        /// <summary>
        /// 刷新遍历数量,在每次遍历之前都要进行一次刷新以校准遍历数量
        /// </summary>
        public int ResetTraversalCount() => TraversalCount = queue.Count;

        public DynamicHashSet()
        {
            queue = new Queue<T>();
            hashSet = new HashSet<T>();
            state = new Dictionary<T, int>();
        }

        /// <summary>
        /// 通过自定义比较器来提高比较效率的构造方式
        /// </summary>
        /// <param name="equalityComparer"></param>
        public DynamicHashSet(IEqualityComparer<T> equalityComparer)
        {
            queue = new Queue<T>();
            hashSet = new HashSet<T>(equalityComparer);
            state = new Dictionary<T, int>(equalityComparer);
        }


        /// <summary>
        /// 入队
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value"></param>
        public void Enqueue(T key)
        {
            if (TryEnqueue(key)) return;
            throw new ArgumentException("Same key exists");
        }
        /// <summary>
        /// 尝试入队
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public bool TryEnqueue(T key)
        {
            if (!hashSet.TryAdd(key)) return false;
            queue.Enqueue(key);
            return true;
        }
        /// <summary>
        /// 从队中移除
        /// </summary>
        /// <param name="key"></param>
        public void Remove(T key)
        {
            if (!TryRemove(key)) throw new ArgumentException("error remove key ");
        }
        /// <summary>
        /// 尝试从队中移除
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public bool TryRemove(T key)
        {
            if (hashSet.Contains(key))
            {
                hashSet.Remove(key);
                if (state.ContainsKey(key)) state[key]++;
                else state.Add(key, 1);
                return true;
            }
            return false;
        }

        /// <summary>
        /// 尝试获取队首
        /// </summary>
        /// <param name="result"></param>
        /// <returns></returns>
        public bool TryPeek(out T result)
        {
            do
            {
                if (queue.TryPeek(out var key))
                {
                    if (state.TryGetValue(key, out int count))
                    {
                        state[key] = --count;
                        if (TraversalCount > 0) TraversalCount--;
                        if (count == 0) state.Remove(key);
                        queue.Dequeue();
                    }
                    else return hashSet.TryGetValue(key, out result);
                }
                else
                {
                    result = default;
                    return false;
                }
            }
            while (true);
        }
        /// <summary>
        /// 获取队首
        /// </summary>
        /// <returns></returns>
        /// <exception cref="InvalidOperationException"></exception>
        public T Peek()
        {
            if (TryPeek(out var result)) return result;
            throw new InvalidOperationException("The operation on an empty container is invalid");
        }

        /// <summary>
        /// 尝试出队
        /// </summary>
        /// <param name="result"></param>
        /// <param name="result"></param>
        /// <returns></returns>
        public bool TryDequeue(out T result)
        {
            if (queue.TryDequeue(out var key))
            {
                while (state.TryGetValue(key, out var count))
                {
                    state[key] = --count;
                    if (TraversalCount > 0) TraversalCount--;
                    if (count == 0) state.Remove(key);
                    if (!queue.TryDequeue(out key))
                    {
                        result = default;
                        return false;
                    }
                }
                if (hashSet.Contains(key))
                {
                    result = key;
                    hashSet.Remove(key);
                    return true;
                }
            }
            result = default;
            return false;
        }

        /// <summary>
        /// 出队
        /// </summary>
        /// <returns></returns>
        /// <exception cref="InvalidOperationException"></exception>
        public T Dequeue()
        {
            if (TryDequeue(out var result))
            {
                return result;
            }
            throw new InvalidOperationException("The operation on an empty container is invalid");
        }


        /// <summary>
        /// 是否存在Key对象
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public bool Contains(T key) => hashSet.Contains(key);

        /// <summary>
        /// 清空
        /// </summary>
        public void Clear()
        {
            hashSet.Clear();
            queue.Clear();
            state.Clear();
        }


        /// <summary>
        /// 无序遍历  不可动态随机移除  迭代器
        /// </summary>
        /// <returns></returns>
        public IEnumerator<T> GetEnumerator()
        {
            return hashSet.GetEnumerator();
        }

        IEnumerator IEnumerable.GetEnumerator()
        {
            return hashSet.GetEnumerator();
        }
    }
}



配套拓展方法

using System;
namespace AirFramework
{
    public static class DynamicHashSetExtensions
    {

        /// <summary>
        /// 尝试从动态HashSet移除一个值并调用Dispose,如果该值存在则返回true
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <typeparam name="K"></typeparam>
        /// <param name="hashSet"></param>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public static bool TryRemoveAndDispose<T>(this DynamicHashSet<T> hashSet, T key) where T : IDisposable
        {
            if (hashSet.Contains(key))
            {
                key.Dispose();
                return true;
            }
            return false;
        }

        /// <summary>
        /// 从动态字典移除一个值并调用其Dispose方法,如果该值不存在将引发异常
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <typeparam name="K"></typeparam>
        /// <param name="hashSet"></param>
        /// <param name="key"></param>
        public static void RemoveAndDispose<T, K>(this DynamicHashSet<T> hashSet, T key) where T : IDisposable
        {
            hashSet.Remove(key);
            key.Dispose();
        }

        /// <summary>
        /// 清空动态字典并调用所有元素的Dispose方法s
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="hashSet"></param>
        public static void ClearAndDispose<T>(this DynamicHashSet<T> hashSet) where T : IDisposable
        {
            while (hashSet.Count > 0)
            {
                hashSet.Dequeue().Dispose();
            }
        }
    }
}