This content has moved - please find it at

Although these pages remain accessible, some content may not display correctly in future as the new blog evolves.


CircularBuffer - a first-in, first-out collection of objects using a fixed buffer

I haven't had much time to work on blog posts recently, but I do have one quick post to make.

One of our current application prototype's stores a bunch of data. Data continuously arrives, but I only want to store so much of it. You could do this with something list a List<T> and just remove items when the collection is too big, but I wanted something a bit more efficient which didn't have to do any sort of resizing or allocation when adding and removing items. Enter the circular buffer.

What is a circular buffer?

To quote Wikipedia, a circular buffer, cyclic buffer or ring buffer is a data structure that uses a single, fixed-size buffer as if it were connected end-to-end. This structure lends itself easily to buffering data streams.

Indeed. Originally I didn't want to invent the wheel, so when I found Circular Buffer for .NET1 I thought I would use that. Unfortunately as soon as I started using, I hit some problems, both in the code and with what I was trying to do. So I stopped working on what I was doing and wrote a full set of tests for the class, fixing bugs as I went, and also adding some more features to handle what I wanted.

Eventually I decided I would put the code up on GitHub as Circular Buffer for .NET doesn't seem to be maintained any longer.

A generic CircularBuffer<T> class for .NET

On our GitHub page you can download a modified version of the original class. I'm not going into too many details here as it's very straightforward to use - if you've used Queue<T> or Stack<T> then you'll be right at home.

  • Get - Removes and returns one or more items from the start of the buffer
  • Put - Adds one or more items to the end of the buffer. If the buffer is full, then items at the start will be overwritten
  • Peek - Retrieve one or more items from the start of the buffer, without removing them
  • PeekLast - Retrieve the last item in the buffer without removing it
  • ToArray - Return all items in the buffer
  • CopyTo - An advanced version of ToArray, allows you to copy items from the buffer into another array
  • Clear - Resets the buffer

There are also some properties to control behaviour or provide state information.

  • Capacity - The total number of items the buffer can hold
  • Size - The current number of items in the buffer
  • AllowOverwrite - When true, new items overwrite the oldest items when the buffer is full. Otherwise, an exception is thrown
  • IsEmpty - true if the buffer is empty
  • IsFull - true if the buffer is full and AllowOverwrite is false


This first example creates a CircularBuffer<T>, adds four items, then retrieves the first item.

CircularBuffer<string> target;
string firstItem;

target = new CircularBuffer<string>(10);

firstItem = target.Get(); // Returns Alpha

This second example shows how the buffer will automatically overwrite the oldest items when full.

CircularBuffer<string> target;
string firstItem;

target = new CircularBuffer<string>(3);

firstItem = target.Get(); // Returns beta

For more examples, see the test class CircularBufferTests as this has tests which cover almost all the code paths.


.NET Framework 2.0 or later.



Update History

  • 2014-06-21 - First published
  • 2020-11-21 - Updated formatting
  • 2023-02-05 - Fixed swapped URLs

About The Author


The founder of Cyotek, Richard enjoys creating new blog content for the site. Much more though, he likes to develop programs, and can often found writing reams of code. A long term gamer, he has aspirations in one day creating an epic video game. Until that time, he is mostly content with adding new bugs to WebCopy and the other Cyotek products.

Leave a Comment

While we appreciate comments from our users, please follow our posting guidelines. Have you tried the Cyotek Forums for support from Cyotek and the community?

Styling with Markdown is supported




# Reply

Is this threadsafe or we have to make it threadsafe>


Richard Moss

# Reply


Thanks for the question. At the moment, it's not thread safe - the initial use I had for the class didn't involve multi-threaded access and I didn't want to burden the base class with having to do processing that wouldn't be used.

Richard Moss