Introduction
CircularArray<T>
is a class that implements a fixed length first in last out 'queue' or buffer. This is useful, for example, if you want to keep, say, the last 30 values in a real-time system. The next value gets put into the array, and then the last value in the array gets pushed out. It does this by using a fixed array, and uses the DivRem
math operator to calculate the position of the head and the tail in the array. It's like the array is circular, with a pointer moving around the circle. The only downside is I had to use an internal facade array to get an array in the sequence I wanted, copying out the values; obviously, this isn't great. I can't think of anything else unless I decide to implement something that appears as an array but is actually a linked list or something.
Background
I needed to keep the last X values in a real-time stock tracking application, efficiently, to work out various things. I couldn't find anything like this at all in Generics (I might be wrong. If I am, can someone please tell me about the built-in class available for this?).
Using the code
The constructor specifies the number of elements to hold. Here, I am holding 'Bar
' objects:
CircularArray<Bar> _circularArray = new CircularArray<Bar>(periods);
Push a value onto the array using the Push
method:
_circularArray.Push(value);
The Get
method gets the element X from the head, e.g., Get(0)
gets the last value you pushed on, Get(1)
gets the second last value you pushed on etc.
_circularArray.Get(i)
The Array
method returns an array sequenced from tail to head, e.g., from the oldest value to the newest values that were pushed on to the queue. One use of this may be to use this as input into a TA-LIB technical analysis library, or anything where you will need an array of the last X values in a real-time system. Here is a snippet of the Unit Test of Array
.
[Test]
public void Push()
{
CircularArray<int> cq = new CircularArray<int>(5);
cq.Push(1);
cq.Push(2);
cq.Push(3);
cq.Push(4);
cq.Push(5);
cq.Push(6);
cq.Push(7);
cq.Push(8);
cq.Push(9);
cq.Push(10);
cq.Push(11);
Assert.AreEqual(7, cq.Array[0]);
Assert.AreEqual(8, cq.Array[1]);
Assert.AreEqual(9, cq.Array[2]);
Assert.AreEqual(10, cq.Array[3]);
Assert.AreEqual(11, cq.Array[4]);
}
I've included the code and Unit Tests in the solution Zip file; everything is there.
Points of interest
As mentioned, I couldn't find anything like this already available. I've probably missed out on some sort of built-in generic Microsoft class. If anyone knows about such a thing, please let me know!
Update: Note, after I posted this, I did read Marc Clifton's article 'A Circular List'. After plugging it into an NUnit test equivalent to the one above:
[Test]
public void CicularList()
{
CircularList<int> cq = new CircularList<int>(5);
cq.Value = 1;
cq.Next();
cq.Value = 2;
cq.Next();
cq.Value = 3;
cq.Next();
cq.Value = 4;
cq.Next();
cq.Value = 5;
cq.Next();
cq.Value = 6;
cq.Next();
cq.Value = 7;
cq.Next();
cq.Value = 8;
cq.Next();
cq.Value = 9;
cq.Next();
cq.Value = 10;
cq.Next();
cq.Value = 11;
cq.Next();
Assert.AreEqual(7, cq[0]);
Assert.AreEqual(8, cq[1]);
Assert.AreEqual(9, cq[2]);
Assert.AreEqual(10, cq[3]);
Assert.AreEqual(11, cq[4]);
}
The array cq
would be 11,7,8,9,10, which is the raw circular array. I was expecting 7,8,9,10,11 - e.g., the last 5 values, oldest to newest. Maybe, I'm using it wrong. 'Failed' above is just against what I expected, so don't read into it. I'm sure CircularList
is useful for some, just not for my purposes. I totally respect and value Marc Clifton's contributions.