A little while ago i had a requirement for a simple, single dimensional, generic collection with a fixed capacity. Now my definition of fixed here is that when the capacity is reached, the oldest item would be pushed off the end of the queue and forgotten. This class would be used to store the last 10 timings to calculate ETAs for downloads in a download manager application but I’m certain there are many more uses for exactly this kind of object!
As you might expect, i thought that the generic Queue<T> would almost certainly do the job but it turns out that despite explicitly setting the collection’s capacity in it’s overloaded constructor, when this capacity is breached, the collection simply doubles in size! IMHO, ‘initialCapacity’ would have made a much more descriptive parameter name given this functionality. Anywho, it turns out that the FCL just doesn’t have anything resembling this functionality (If I’ve missed something, please do tell!) so i set out to write my own.
The class is listed below. There is obviously some delegate functionality (Sort, Find, FindAll etc…) missing that many people would want to implement but I’ve left that up to you since it does all i needed to do at the time. Hopefully this will be of use to someone.
using System; using System.Collections.Generic; using System.Text; using System.Collections; class QueueFrame<t> : IEnumerable<t> { private T[] values; private int topIx = 0; private int capacity; public int Count { get { return topIx; } } public QueueFrame(int frameCapacity) { values = new T[frameCapacity]; capacity = frameCapacity; } public void Enqueue(T t) { if (topIx > values.Length - 1) { //shift array elements back one ShiftBackOne(ref values); values[topIx - 1] = t; } else { values[topIx++] = t; } } public T this[int Ix] { get { return values[Ix]; } set { values[Ix] = value; } } private void ShiftBackOne(ref T[] t) { T[] temp = new T[capacity]; for (int i = 1; i <= t.Length - 1; i++) { temp[i - 1] = t[i]; } t = temp; } public T Dequeue() { return values[--topIx]; } public IEnumerator<t> GetEnumerator() { for (int i = 0; --i >= 0; ) { yield return values[i]; } } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } }
Happy Coding!
