대기열 크기 제한 .NET에서?
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는 인터페이스하도록 프로그래밍되고 서브 클래 싱되도록 설계되었습니다. 대부분의 공용 메서드는 가상이며 어떤 클래스도 봉인되지 않습니다. 이렇게하면 .NET Framework 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>를 사용합니다. 버퍼의 크기에 도달하면 이전 항목을 새 항목으로 바꿉니다.
참고 : 항목을 임의로 제거 할 수 없습니다. Remove (T item) 메서드를 false를 반환하도록 설정했습니다. 원하는 경우 항목을 임의로 제거하도록 수정할 수 있습니다.
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
}
동시 솔루션
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
for 를 실행할 필요가 없습니다 TryDequeue
.
누구에게나 유용하다면 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의 상위 결과였습니다.)
참고 URL : https://stackoverflow.com/questions/1292/limit-size-of-queuet-in-net
'Programing' 카테고리의 다른 글
웹 API 생성 API 키 (0) | 2020.12.13 |
---|---|
생성자가 템플릿 인수를 추론 할 수없는 이유는 무엇입니까? (0) | 2020.12.13 |
통합 테스트에 필요한 데이터베이스 데이터 (0) | 2020.12.13 |
다중 통화 모범 사례 및 구현 (0) | 2020.12.13 |
Python (.T)의 구문 (0) | 2020.12.13 |