CircularBuffer<T> Class
Definition
- Namespace
- Bodu.Collections.Generic
- Assembly
- Bodu.Collections.dll
- Package
- Bodu.Collections 1.0.0
- Source
- CircularBuffer{T}.cs
Represents a fixed-size, first-in first-out (FIFO) circular buffer with optional overwrite-on-full semantics. Elements are inserted at the tail and removed from the head; once the buffer reaches Capacity, the AllowOverwrite property determines whether further inserts evict the oldest element or are rejected.
public sealed class CircularBuffer<T> : RingBackedCollection<T>, ICollection, IReadOnlyCollection<T>, IEnumerable<T>, IEnumerable
Type Parameters
TSpecifies the type of elements stored in the buffer.
- Inheritance
-
CircularBuffer<T>
- Implements
-
IEnumerable<T>
- Inherited Members
- Extension Methods
Examples
// Sliding window of the three most recent samples - overwrite-on-full is the default.
var window = new CircularBuffer<int>(capacity: 3);
window.Enqueue(1);
window.Enqueue(2);
window.Enqueue(3);
window.Enqueue(4); // evicts 1; ItemEvicted fires with value 1
Console.WriteLine(window.Peek()); // 2 (oldest remaining)
// Fixed FIFO queue that rejects further pushes when full.
var bounded = new CircularBuffer<int>(capacity: 2, allowOverwrite: false);
bounded.Enqueue(10);
bounded.Enqueue(20);
bool added = bounded.TryEnqueue(30); // false - buffer is full
Remarks
CircularBuffer<T> is the single-ended member of the ring-backed collection family. Like Deque<T>, it stores its elements in a contiguous backing array using head and tail indices that wrap around modulo the capacity, giving O(1) cost for adds, removes, and peeks.
The behavior on a full buffer is controlled by the mutable AllowOverwrite property:
-
AllowOverwrite = true(the default for the parameterless and capacity-only constructors) - adds to a full buffer evict the oldest element to make room for the new one. The ItemEvicting event fires before the eviction (and may veto it by throwing) and the ItemEvicted event fires after. -
AllowOverwrite = false- Enqueue(T) throws InvalidOperationException when the buffer is full; TryEnqueue(T) returns false without modifying state.
Key operations:
- Enqueue(T) / TryEnqueue(T) - add an element at the tail.
- Dequeue() / TryDequeue(out T) - remove and return the oldest (head) element.
- Peek() / TryPeek(out T) - read the oldest element without removing it.
-
Inherited TrimExcess() - shrink the backing array to
Count.
For a double-ended counterpart with the same fixed-vs-growable choice, see Deque<T>. For thread-safe
concurrent FIFO access, see ConcurrentCircularBuffer<T> in the Bodu.Collections.Concurrent package;
CircularBuffer<T> itself is not thread-safe.
CircularBuffer<T> accepts null values for reference types and allows duplicate elements.
Constructors
CircularBuffer()
Initializes a new instance of the CircularBuffer<T> class using the default capacity and allowing overwrites by default.
public CircularBuffer()
CircularBuffer(IEnumerable<T>)
Initializes a new instance of the CircularBuffer<T> class by copying elements from the specified collection, using the default capacity and allowing overwriting if needed.
public CircularBuffer(IEnumerable<T> collection)
Parameters
collectionIEnumerable<T>The collection from which elements are copied. Must not be null.
Exceptions
- ArgumentNullException
Thrown when
collectionis null.
CircularBuffer(IEnumerable<T>, int)
Initializes a new instance of the CircularBuffer<T> class by copying elements from the specified collection and applying the specified capacity. Overwriting is enabled by default.
public CircularBuffer(IEnumerable<T> collection, int capacity)
Parameters
collectionIEnumerable<T>The collection from which elements are copied. Must not be null.
capacityintThe maximum number of elements the buffer can contain. Must be greater than zero.
Exceptions
- ArgumentNullException
Thrown when
collectionis null.- ArgumentOutOfRangeException
Thrown when
capacityis less than or equal to zero.
CircularBuffer(IEnumerable<T>, int, bool)
Initializes a new instance of the CircularBuffer<T> class by copying elements from the specified collection, applying the specified capacity and overwrite behavior.
public CircularBuffer(IEnumerable<T> collection, int capacity, bool allowOverwrite)
Parameters
collectionIEnumerable<T>The collection from which elements are copied. Must not be null.
capacityintThe maximum number of elements the buffer can contain. Must be greater than zero.
allowOverwriteboolIf true, the most recent elements from the collection are retained if its size exceeds
capacity. If false, the collection size must not exceedcapacity, or an exception is thrown.
Exceptions
- ArgumentNullException
Thrown when
collectionis null.- ArgumentOutOfRangeException
Thrown when
capacityis less than or equal to zero.- InvalidOperationException
Thrown when
allowOverwriteis false and the collection contains more elements than the buffer capacity.
CircularBuffer(int)
Initializes a new instance of the CircularBuffer<T> class with the specified capacity, allowing overwrites when full.
public CircularBuffer(int capacity)
Parameters
capacityintThe maximum number of elements the buffer can contain. Must be greater than zero.
Exceptions
- ArgumentOutOfRangeException
Thrown when
capacityis less than or equal to zero.
CircularBuffer(int, bool)
Initializes a new instance of the CircularBuffer<T> class with the specified capacity and overwrite behavior.
public CircularBuffer(int capacity, bool allowOverwrite)
Parameters
capacityintThe maximum number of elements the buffer can contain. Must be greater than zero.
allowOverwritebooltrue to allow the buffer to automatically overwrite the oldest elements when full; false to prevent adding new elements when the buffer has reached capacity, which will cause an exception to be thrown during insertion.
Exceptions
- ArgumentOutOfRangeException
Thrown when
capacityis less than or equal to zero.
Properties
AllowOverwrite
Gets or sets a value indicating whether the CircularBuffer<T> will automatically overwrite the oldest element when capacity is reached.
public bool AllowOverwrite { get; set; }
Property Value
Methods
Dequeue()
Removes and returns the oldest element from the buffer.
public T Dequeue()
Returns
- T
The oldest element in the buffer.
Exceptions
- InvalidOperationException
Thrown if the buffer is empty when Dequeue() is called.
Enqueue(T)
Adds an element to the end of the buffer.
public void Enqueue(T item)
Parameters
itemTThe element to add. Can be null for reference types.
Exceptions
- InvalidOperationException
Thrown if the buffer is at full capacity and AllowOverwrite is false.
Peek()
Returns the oldest element in the CircularBuffer<T> without removing it.
public T Peek()
Returns
- T
The element at the front of the buffer (the oldest item).
Exceptions
- InvalidOperationException
Thrown when the buffer is empty (i.e., Count equals
0).
TryDequeue(out T)
Attempts to remove and return the oldest element from the CircularBuffer<T> without throwing an exception.
public bool TryDequeue(out T item)
Parameters
itemTWhen this method returns, contains the dequeued element if one was available; otherwise, the default value of
T.
Returns
TryEnqueue(T)
Attempts to add an element to the end of the CircularBuffer<T> without throwing an exception.
public bool TryEnqueue(T item)
Parameters
itemTThe element to add. Can be null for reference types.
Returns
- bool
true if the item was successfully enqueued; false if the buffer is full and AllowOverwrite is false.
TryPeek(out T)
Attempts to retrieve the oldest element from the CircularBuffer<T> without removing it.
public bool TryPeek(out T item)
Parameters
itemTWhen this method returns, contains the oldest element if the buffer is not empty; otherwise, contains the default value for
T.
Returns
Events
ItemEvicted
Occurs immediately after an item has been evicted from the CircularBuffer<T> due to capacity limits.
public event Action<T>? ItemEvicted
Event Type
- Action<T>
Remarks
This event is raised only when the buffer reaches capacity and AllowOverwrite is true.
Important: Exceptions thrown by event handlers are not caught and will propagate to the caller of Enqueue(T) or TryEnqueue(T). Consumers should ensure event handlers are exception-safe.
ItemEvicting
Occurs immediately before an item is evicted from the CircularBuffer<T> due to capacity limits.
public event Action<T>? ItemEvicting
Event Type
- Action<T>
Remarks
This event is raised only when the buffer has reached its capacity and AllowOverwrite is true.
Important: Any exception thrown from a handler vetoes the eviction in place - the oldest element is not removed, the new element is not stored, the count, head, and tail indices are unchanged, and the exception propagates to the caller of Enqueue(T) or TryEnqueue(T). Event handlers should therefore avoid throwing unless the veto is intentional.
Applies to
| Product | Versions |
|---|---|
| .NET | 8, 10 |