나는 용량이 2로 초기화 된 큐 <T> 개체를 가지고 있지만 분명히 그 개체는 용량이고 계속 항목을 추가 할 때 계속 확장됩니다. 한계에 도달했을 때 자동으로 항목을 대기열에서 제외하거나 이미 상속 된 클래스를 만들 때 가장 좋은 해결책 인 객체가 이미 있습니까?.NET의 대기열 크기 제한 <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);
}
}
왜 크기가 2 인 배열을 사용하지 않습니까? 대기열은 동적으로 성장하고 축소 할 수 있어야합니다.
Queue<T>
인스턴스 주위에 래퍼 클래스를 만들고 <T>
개체를 대기열에 추가 할 때마다 큐의 크기를 확인하십시오. 2보다 큰 경우 첫 번째 항목을 큐에서 빼냅니다.
자신 만의 클래스를 만들어야합니다. 링 버퍼가 사용자의 필요에 맞을 것입니다.
배열을 제외한 용량을 지정할 수있는 .NET의 데이터 구조는이 데이터를 사용하여 내부 데이터를 보유하는 데 사용되는 내부 데이터 구조를 작성합니다.
예를 들어, 목록의 경우 용량은 내부 배열의 크기를 지정하는 데 사용됩니다. 목록에 요소를 추가하기 시작하면 인덱스 0부터 배열에 채우기를 시작하고 용량에 도달하면 용량을 새로운 높은 용량으로 늘리고 계속 채 웁니다.
C5 Library을 가져 오는 것이 좋습니다. 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();
}
}
}
}
이 코드는 사용자가 찾고 있던 것과 정확히 일치해야한다고 생각합니다.
이 잘 나는이 클래스의 뜻은 당신을 도움이되기를 바랍니다 :
내부적으로 원형 FIFO 버퍼 사이즈가 지정된 큐 <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
}
이 코드를 사용하면 제한된 크기의 큐를 가질 수 있다고 생각합니다. 또한 Circular 버퍼입니다. –
를 항목을 제거하기 위해 수정할 수있는, 내가 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; }
}
}
너무 커지면 가장 오래된 항목 (스택 하단)이 제거됩니다.
내가 큐 크기가 초과되지 않았 음을 보장 제한 등록 정보의 설정 내에서 호출 코드를 약간 증강이 코드는 99 % 정확합니다. 그러나 Peek 또는 Pop을 스택에 넣지 않고 호출하면 인덱스가 -1 일 때 충돌이 발생합니다. 인덱스 경계 검사를 추가하면이 문제를 쉽게 해결할 수 있습니다. – Contango
Peek 및 Pop()에 다음을 추가 할 것을 제안하십시오. \t \t \t if ((_stack.Count - 1) <0) throw new exception ("처음 푸시하지 않고 Peek 또는 Pop을 할 수 없습니다."). 이것은 프로그래머에게이 코너 케이스를 경고하고,이 클래스를 사용할 때 명심해야한다. TryPeek 또는 TryPop을 추가 할 수도 있습니다. TryPeek는 Microsoft가 ConcurrentDictionary 구현을 통해 취한 접근 방식입니다. – Contango
레코드의 경우이 코드는 추가 잠금 없이는 스레드 안전하지 않습니다 (이는 절대적으로 좋으며 스레드 안전은이 클래스의 디자인 사양의 일부가 아닙니다). – Contango
- 1. 대기열 크기 제한 설정
- 2. 데이터 대기열 크기 제한 - iSeries에서 Java 로의 통신
- 3. .NET의 화면 텍스트 크기
- 4. Azure 대기열 저장소 메시지 크기
- 5. 셀렌 그리드 : 허브의 대기열 크기?
- 6. .NET의 등록 정보 제한 값
- 7. C# 파일 크기 제한
- 8. ASP.NET 세션 크기 제한
- 9. 블록 크기의 크기 제한
- 10. CDO의 메시지 크기 제한?
- 11. 브라우저 응답 크기 제한
- 12. 스칼라 사서함 크기 제한
- 13. VS2005 : 힙 크기 제한
- 14. httplib2로 응답 크기 제한
- 15. Sqlite 필드 크기 제한
- 16. 제한 UITextField 크기
- 17. 클립 보드 크기 제한
- 18. ASP 페이지 크기 제한
- 19. 펄 파일 크기 제한
- 20. 제한 크기 폴더
- 21. innerHTML 크기 제한
- 22. 하스켈 튜플 크기 제한
- 23. WPF 확장기의 크기 제한
- 24. GWT 디자이너 크기 제한
- 25. 크롬 쿠키 크기 제한
- 26. 쓰기 파일의 크기 제한
- 27. 매트릭스 크기 제한
- 28. 캐시 디렉토리의 크기 제한
- 29. mysql 테이블의 크기 제한
- 30. 은 크기 제한
(이 질문은 "C# 제한 스택 크기"에 대한 상단 구글 결과였다) 한도 - 단순한 한도 초과, 데 큐잉. 그 외,이 솔루션은 멋지고 간단합니다. 감사합니다. – Scott
'제한'속성의 '설정자'코드를 변경하는 것이 좋습니다. –
이 클래스에는 Marcus Griep이 매우 암시 한 제한이 있습니다 :'Enqueue' 메쏘드가'New'로 선언 되었기 때문에 (Queue .Enqueue는 가상이 아닙니다.) 누군가가 당신의'LimitQueue '을 '대기열 '에 추가하면 제한을 적용하지 않고 원하는만큼 항목을 추가 할 수 있습니다. 나는 또한'if (this.Count> = this.Limit)'를'while (this.Count> = this.Limit)'으로 변경하는 것을 권하고 싶다. 단지 안전한면에있다. (방금 언급 한 시나리오에서 예를 들어). –