Как зайти в Даркнет?!
25th January, 01:11
8
0
Как в tkinter из поля ввода Entry получить значение в одну переменную и обновить строку кнопкой, затем получить ещё одно введённое значение и затем сложить их. Ниже пример кода
21st July, 19:00
899
0
Программа, которая создает фейковые сервера в поиске игровых серверов CS 1.6 Steam
21st March, 17:43
952
0
Очень долго работает Update запрос Oracle
27th January, 09:58
916
0
не могу запустить сервер на tomcat HTTP Status 404 – Not Found
21st January, 18:02
907
0
Где можно найти фрилансера для выполнения поступающих задач, на постоянной основе?
2nd December, 09:48
942
0
Разработка мобильной кроссплатформенной военной игры
16th July, 17:57
1727
0
период по дням
25th October, 10:44
3957
0
Пишу скрипты для BAS только на запросах
16th September, 02:42
3722
0
Некорректный скрипт для закрытия блока
14th April, 18:33
4614
0
прокидывать exception в блоках try-catch JAVA
11th March, 21:11
4382
0
Помогите пожалуйста решить задачи
24th November, 23:53
6087
0
Не понимаю почему не открывается детальное описание продукта
11th November, 11:51
4352
0
Нужно решить задачу по программированию на массивы
27th October, 18:01
4400
0
Метода Крамера С++
23rd October, 11:55
4309
0
помогите решить задачу на C++
22nd October, 17:31
4002
0
Помогите решить задачу на python с codeforces
22nd October, 11:11
4492
0
Python с нуля: полное руководство для начинающих
18th June, 13:58
2599
0
Предельный размер очереди в .NET?
У меня есть объект Queue<T>, который я инициализировал до емкости 2, но очевидно, что это просто емкость, и она продолжает расширяться по мере добавления элементов. Есть ли уже объект, который автоматически отменяет запрос элемента при достижении предела, или это лучшее решение для создания моего собственного наследуемого класса?
Я придумал базовую версию того, что я ищу, она не идеальна, но она будет делать свою работу, пока не появится что-то лучшее.
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 запрограммирован на интерфейс и предназначен для подклассов. Большинство открытых методов являются виртуальными, и ни один из классов не запечатан. Таким образом, вам не придется использовать это жуткое ключевое слово "new", которое не сработало бы, если бы ваш 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();
}
}
}
}
Я думаю, что этот код должен делать именно то, что вы искали.
Вы должны создать свой собственный класс, ringbuffer, вероятно, будет соответствовать вашим потребностям.
Структуры данных в .NET, которые позволяют указать емкость, за исключением массива, используют это для построения внутренней структуры данных, используемой для хранения внутренних данных.
Например, для списка емкость используется для определения размера внутреннего массива. Когда вы начинаете добавлять элементы в список, он начинает заполнять этот массив от индекса 0 и выше, а когда он достигает вашей емкости, он увеличивает емкость до новой более высокой емкости и продолжает заполнять ее.
Почему бы вам просто не использовать массив размером 2? Предполагается, что очередь может динамически расти и сокращаться.
Или создайте класс-оболочку вокруг экземпляра экземпляра Queue<T> , и каждый раз, когда один из них запрашивает объект <T> , проверьте размер очереди. Если размер больше 2, удалите первый элемент из списка.
Ну я надеюсь что этот класс поможет вам:
Внутри кругового буфера FIFO используется символ Queue<T> с указанным размером.
Как только размер буфера будет достигнут, он заменит старые элементы новыми.
NOTE: вы не можете удалять элементы случайным образом. Я установил метод 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
}
Если это кому-то пригодится, я сделал 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; }
}
}
Он удаляет самый старый элемент (нижняя часть стека), когда он становится слишком большим.
(Этот вопрос был лучшим результатом Google для "C# limit stack size")
Параллельное Решение
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);
}
}
}
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 .