yotiky Tech Blog

とあるエンジニアの備忘録

C# - 固定サイズのキュー

ラッパークラス

最小限の実装。Queue がラップされるので Queue で必要な機能は全部中継する必要がある。

public class FixedSizeQueue<T>
{
    private ConcurrentQueue<T> queue = new ConcurrentQueue<T>();
    private object lockObject = new Object();
    public int Size { get; }

    public FixedSizeQueue(int size)
    {
        Size = size;
    }
    public void Enqueue(T item)
    {
        lock (lockObject)
        {
            queue.Enqueue(item);
            while (Size < queue.Count)
            {
                queue.TryDequeue(out var _);
            }
        }
    }
    public bool TryDequeue(out T result)
        => queue.TryDequeue(out result);
    public int Count()
        => queue.Count;
}

拡張メソッド

必要な機能中継するのが面倒な時に、Enueue する時に長さを指定する簡易機能。

public static class QueueExtensions
{
    public static void EnqueueFixedSize<T>(this Queue<T> queue, T item, int size)
    {
        queue.Enqueue(item);
        while (size < queue.Count)
        {
            queue.TryDequeue(out var _);
        }
    }
    public static void EnqueueFixedSize<T>(this ConcurrentQueue<T> queue, T item, int size, object lockObject)
    {
        lock (lockObject)
        {
            queue.Enqueue(item);
            while (size < queue.Count)
            {
                queue.TryDequeue(out var _);
            }
        }
    }
    public static void EnqueueFixedSize<T>(this ConcurrentQueue<T> queue, IEnumerable<T> items, int size, object lockObject)
    {
        lock (lockObject)
        {
            foreach (var item in items)
            {
                queue.Enqueue(item);
            }
            while (size < queue.Count)
            {
                queue.TryDequeue(out var _);
            }
        }
    }
}