Table of Contents

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

T

Specifies the type of elements stored in the buffer.

Inheritance
CircularBuffer<T>
Implements
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:

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

collection IEnumerable<T>

The collection from which elements are copied. Must not be null.

Exceptions

ArgumentNullException

Thrown when collection is 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

collection IEnumerable<T>

The collection from which elements are copied. Must not be null.

capacity int

The maximum number of elements the buffer can contain. Must be greater than zero.

Exceptions

ArgumentNullException

Thrown when collection is null.

ArgumentOutOfRangeException

Thrown when capacity is 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

collection IEnumerable<T>

The collection from which elements are copied. Must not be null.

capacity int

The maximum number of elements the buffer can contain. Must be greater than zero.

allowOverwrite bool

If true, the most recent elements from the collection are retained if its size exceeds capacity. If false, the collection size must not exceed capacity, or an exception is thrown.

Exceptions

ArgumentNullException

Thrown when collection is null.

ArgumentOutOfRangeException

Thrown when capacity is less than or equal to zero.

InvalidOperationException

Thrown when allowOverwrite is 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

capacity int

The maximum number of elements the buffer can contain. Must be greater than zero.

Exceptions

ArgumentOutOfRangeException

Thrown when capacity is 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

capacity int

The maximum number of elements the buffer can contain. Must be greater than zero.

allowOverwrite bool

true 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 capacity is 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

bool

true to overwrite the oldest item when the buffer is full; false to throw an exception instead of overwriting.

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

item T

The 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

item T

When this method returns, contains the dequeued element if one was available; otherwise, the default value of T.

Returns

bool

true if an item was successfully dequeued; otherwise, false if the buffer was empty.

TryEnqueue(T)

Attempts to add an element to the end of the CircularBuffer<T> without throwing an exception.

public bool TryEnqueue(T item)

Parameters

item T

The 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

item T

When this method returns, contains the oldest element if the buffer is not empty; otherwise, contains the default value for T.

Returns

bool

true if an item was successfully retrieved; false if the buffer is empty.

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

ProductVersions
.NET8, 10