문제

용량 2로 초기화한 Queue<T> 개체가 있는데 분명히 용량일 뿐이고 항목을 추가하면 계속 확장됩니다.제한에 도달하면 항목을 자동으로 대기열에서 빼는 객체가 이미 있습니까, 아니면 상속된 클래스를 직접 생성하는 가장 좋은 솔루션이 있습니까?

도움이 되었습니까?

해결책

내가 찾고 있는 것의 기본 버전을 만들었습니다. 완벽하지는 않지만 더 나은 것이 나올 때까지 작업을 수행할 것입니다.

public class LimitedQueue<T> : Queue<T>
{
    public int Limit { get; set; }

    public LimitedQueue(int limit) : base(limit)
    {
        Limit = limit;
    }

    public new void Enqueue(T item)
    {
        while (Count >= Limit)
        {
            Dequeue();
        }
        base.Enqueue(item);
    }
}

다른 팁

끌어올리는 걸 추천드려요 C5 라이브러리.SCG(System.Collections.Generic)와 달리 C5는 인터페이스하도록 프로그래밍되어 있으며 하위 클래스로 분류되도록 설계되었습니다.대부분의 공개 메소드는 가상이며 어떤 클래스도 봉인되지 않습니다.이렇게 하면 다음과 같은 경우 실행되지 않는 이상한 "새" 키워드를 사용할 필요가 없습니다. LimitedQueue<T> 에 캐스팅됐다 SCG.Queue<T>.C5를 사용하고 이전과 거의 동일한 코드를 사용하면 다음에서 파생됩니다. CircularQueue<T>.그만큼 CircularQueue<T> 실제로 스택과 큐를 모두 구현하므로 거의 무료로 제한이 있는 두 옵션을 모두 얻을 수 있습니다.아래에 3.5 구성으로 다시 작성했습니다.

using C5;

public class LimitedQueue<T> : CircularQueue<T>
{
    public int Limit { get; set; }

    public LimitedQueue(int limit) : base(limit)
    {
        this.Limit = limit;
    }

    public override void Push(T item)
    {
        CheckLimit(false);
        base.Push(item);
    }

    public override void Enqueue(T item)
    {
        CheckLimit(true);
        base.Enqueue(item);
    }

    protected virtual void CheckLimit(bool enqueue)
    {
        while (this.Count >= this.Limit)
        {
            if (enqueue)
            {
                this.Dequeue();
            }
            else
            {
                this.Pop();
            }
        }
    }
}

내 생각에 이 코드는 당신이 찾고 있던 것과 정확히 일치해야 한다고 생각합니다.

당신은 자신만의 클래스를 만들어야 하며, 링버퍼가 아마도 당신의 필요에 맞을 것입니다.

배열을 제외하고 용량을 지정할 수 있는 .NET의 데이터 구조는 이를 사용하여 내부 데이터를 보유하는 데 사용되는 내부 데이터 구조를 구축합니다.

예를 들어 목록의 경우 용량은 내부 배열의 크기를 지정하는 데 사용됩니다.목록에 요소를 추가하기 시작하면 인덱스 0부터 이 배열을 채우기 시작하고, 용량에 도달하면 용량을 새로운 더 높은 용량으로 늘리고 계속해서 채웁니다.

크기가 2인 배열을 사용하지 않는 이유는 무엇입니까?대기열은 동적으로 늘리고 줄일 수 있어야 합니다.

또는 인스턴스 주위에 래퍼 클래스를 만듭니다. Queue<T> 인스턴스를 대기열에 추가할 때마다 <T> 개체의 대기열 크기를 확인하세요.2보다 크면 첫 번째 항목을 대기열에서 제거합니다.

이 수업이 당신에게 도움이 되기를 바랍니다:
내부적으로 순환 FIFO 버퍼는 지정된 크기의 Queue<T>를 사용합니다.버퍼 크기에 도달하면 이전 항목이 새 항목으로 대체됩니다.

메모:항목을 무작위로 제거할 수는 없습니다.false를 반환하도록 Remove(T 항목) 메서드를 설정했습니다.원하는 경우 무작위로 항목을 제거하도록 수정할 수 있습니다.

public class CircularFIFO<T> : ICollection<T> , IDisposable
{
    public Queue<T> CircularBuffer;

    /// <summary>
    /// The default initial capacity.
    /// </summary>
    private int capacity = 32;

    /// <summary>
    /// Gets the actual capacity of the FIFO.
    /// </summary>
    public int Capacity
    {
        get { return capacity; }          
    }

    /// <summary>
    ///  Initialize a new instance of FIFO class that is empty and has the default initial capacity.
    /// </summary>
    public CircularFIFO()
    {            
        CircularBuffer = new Queue<T>();
    }

    /// <summary>
    /// Initialize a new instance of FIFO class that is empty and has the specified initial capacity.
    /// </summary>
    /// <param name="size"> Initial capacity of the FIFO. </param>
    public CircularFIFO(int size)
    {
        capacity = size;
        CircularBuffer = new Queue<T>(capacity);
    }

    /// <summary>
    /// Adds an item to the end of the FIFO.
    /// </summary>
    /// <param name="item"> The item to add to the end of the FIFO. </param>
    public void Add(T item)
    {
        if (this.Count >= this.Capacity)
            Remove();

        CircularBuffer.Enqueue(item);
    }

    /// <summary>
    /// Adds array of items to the end of the FIFO.
    /// </summary>
    /// <param name="item"> The array of items to add to the end of the FIFO. </param>
     public void Add(T[] item)
    { 
        int enqueuedSize = 0;
        int remainEnqueueSize = this.Capacity - this.Count;

        for (; (enqueuedSize < item.Length && enqueuedSize < remainEnqueueSize); enqueuedSize++)
            CircularBuffer.Enqueue(item[enqueuedSize]);

        if ((item.Length - enqueuedSize) != 0)
        {
            Remove((item.Length - enqueuedSize));//remaining item size

            for (; enqueuedSize < item.Length; enqueuedSize++)
                CircularBuffer.Enqueue(item[enqueuedSize]);
        }           
    }

    /// <summary>
    /// Removes and Returns an item from the FIFO.
    /// </summary>
    /// <returns> Item removed. </returns>
    public T Remove()
    {
        T removedItem = CircularBuffer.Peek();
        CircularBuffer.Dequeue();

        return removedItem;
    }

    /// <summary>
    /// Removes and Returns the array of items form the FIFO.
    /// </summary>
    /// <param name="size"> The size of item to be removed from the FIFO. </param>
    /// <returns> Removed array of items </returns>
    public T[] Remove(int size)
    {
        if (size > CircularBuffer.Count)
            size = CircularBuffer.Count;

        T[] removedItems = new T[size];

        for (int i = 0; i < size; i++)
        {
            removedItems[i] = CircularBuffer.Peek();
            CircularBuffer.Dequeue();
        }

        return removedItems;
    }

    /// <summary>
    /// Returns the item at the beginning of the FIFO with out removing it.
    /// </summary>
    /// <returns> Item Peeked. </returns>
    public T Peek()
    {
        return CircularBuffer.Peek();
    }

    /// <summary>
    /// Returns the array of item at the beginning of the FIFO with out removing it.
    /// </summary>
    /// <param name="size"> The size of the array items. </param>
    /// <returns> Array of peeked items. </returns>
    public T[] Peek(int size)
    {
        T[] arrayItems = new T[CircularBuffer.Count];
        CircularBuffer.CopyTo(arrayItems, 0);

        if (size > CircularBuffer.Count)
            size = CircularBuffer.Count;

        T[] peekedItems = new T[size];

        Array.Copy(arrayItems, 0, peekedItems, 0, size);

        return peekedItems;
    }

    /// <summary>
    /// Gets the actual number of items presented in the FIFO.
    /// </summary>
    public int Count
    {
        get
        {
            return CircularBuffer.Count;
        }
    }

    /// <summary>
    /// Removes all the contents of the FIFO.
    /// </summary>
    public void Clear()
    {
        CircularBuffer.Clear();
    }

    /// <summary>
    /// Resets and Initialize the instance of FIFO class that is empty and has the default initial capacity.
    /// </summary>
    public void Reset()
    {
        Dispose();
        CircularBuffer = new Queue<T>(capacity);
    }

    #region ICollection<T> Members

    /// <summary>
    /// Determines whether an element is in the FIFO.
    /// </summary>
    /// <param name="item"> The item to locate in the FIFO. </param>
    /// <returns></returns>
    public bool Contains(T item)
    {
        return CircularBuffer.Contains(item);
    }

    /// <summary>
    /// Copies the FIFO elements to an existing one-dimensional array. 
    /// </summary>
    /// <param name="array"> The one-dimensional array that have at list a size of the FIFO </param>
    /// <param name="arrayIndex"></param>
    public void CopyTo(T[] array, int arrayIndex)
    {
        if (array.Length >= CircularBuffer.Count)
            CircularBuffer.CopyTo(array, 0);           
    }

    public bool IsReadOnly
    {
        get { return false; }
    }

    public bool Remove(T item)
    {
        return false; 
    }

    #endregion

    #region IEnumerable<T> Members

    public IEnumerator<T> GetEnumerator()
    {
       return CircularBuffer.GetEnumerator();
    }

    #endregion

    #region IEnumerable Members

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

    #endregion

    #region IDisposable Members

    /// <summary>
    /// Releases all the resource used by the FIFO.
    /// </summary>
    public void Dispose()
    {          
        CircularBuffer.Clear();
        CircularBuffer = null;
        GC.Collect();
    }

    #endregion
}

누군가에게 도움이 된다면 제가 만들었습니다. LimitedStack<T>.

public class LimitedStack<T>
{
    public readonly int Limit;
    private readonly List<T> _stack;

    public LimitedStack(int limit = 32)
    {
        Limit = limit;
        _stack = new List<T>(limit);
    }

    public void Push(T item)
    {
        if (_stack.Count == Limit) _stack.RemoveAt(0);
        _stack.Add(item);
    }

    public T Peek()
    {
        return _stack[_stack.Count - 1];
    }

    public void Pop()
    {
        _stack.RemoveAt(_stack.Count - 1);
    }

    public int Count
    {
        get { return _stack.Count; }
    }
}

너무 커지면 가장 오래된 항목(스택의 맨 아래)을 제거합니다.

(이 질문은 "C# 제한 스택 크기"에 대한 Google의 상위 검색 결과였습니다.)

동시 솔루션

public class LimitedConcurrentQueue<ELEMENT> : ConcurrentQueue<ELEMENT>
{
    public readonly int Limit;

    public LimitedConcurrentQueue(int limit)
    {
        Limit = limit;
    }

    public new void Enqueue(ELEMENT element)
    {
        base.Enqueue(element);
        if (Count > Limit)
        {
            TryDequeue(out ELEMENT discard);
        }
    }
}

메모:부터 Enqueue 요소 추가를 제어하고 한 번에 하나씩 수행하므로 while ~을 위한 TryDequeue.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top