RingBackedCollection<T> Class
Definition
Provides the shared low-level mechanics for ring-buffer-backed collections - a contiguous backing array, head/tail indices with modulo wrap, a live element count, and a structural-version counter - as a reusable base type for CircularBuffer<T> and Deque<T>.
public abstract class RingBackedCollection<T> : ICollection, IReadOnlyCollection<T>, IEnumerable<T>, IEnumerable
Type Parameters
TSpecifies the type of elements stored in the collection.
- Inheritance
-
RingBackedCollection<T>
- Implements
-
IEnumerable<T>
- Derived
-
Deque<T>
- Inherited Members
- Extension Methods
Examples
// The common surface is consumed through a concrete derivative - CircularBuffer<T> here.
// The same Count, Capacity, IsEmpty, indexer, ToArray, and TrimExcess members are available
// on every RingBackedCollection<T> subtype.
RingBackedCollection<int> ring = new CircularBuffer<int>(capacity: 4);
((CircularBuffer<int>)ring).Enqueue(10);
((CircularBuffer<int>)ring).Enqueue(20);
Console.WriteLine(ring.Count); // 2
Console.WriteLine(ring.Capacity); // 4
Console.WriteLine(ring[0]); // 10 - head-relative indexer
ring.TrimExcess(); // shrink Capacity towards Count
Remarks
RingBackedCollection<T> is intended as an extension point for new ring-backed collection types. It owns the storage and exposes:
- A read-only public surface for consumers - Capacity, Count, IsEmpty, the head-relative indexer, Clear(), Contains(T), CopyTo(T[], int), ToArray(), and TrimExcess().
- The framework collection interfaces - ICollection, IEnumerable<T>, and IReadOnlyCollection<T>.
- A single shared RingBackedCollection<T>.Enumerator nested struct that walks the live region in head-to-tail logical order and uses a structural-version token to detect concurrent modification.
- Protected primitives for derived types - AddTail(T), AddHead(T), RemoveHead(), RemoveTail(), PeekHead(), PeekTail(), OverwriteTail(T), and Resize(int).
The protected mutators perform no capacity or emptiness validation: derived classes must enforce those contracts before calling. This keeps the hot path branch-free in the common cases. Each mutator bumps the internal structural-version counter so any in-flight enumerators are correctly invalidated.
Concrete derived types layer their own public API on top of these primitives:
-
CircularBuffer<T> adds the single-ended
Enqueue/Dequeue/Peeksurface with anAllowOverwritetoggle and eviction events. -
Deque<T> adds the double-ended
AddFirst/AddLast/RemoveFirst/RemoveLast/PeekFirst/PeekLastsurface, with anAllowGrowtoggle for fixed-vs-growable behavior.
This type is not thread-safe. For thread-safe single-ended FIFO access, use ConcurrentCircularBuffer<T>
in the Bodu.Collections.Concurrent package - its lock-free Vyukov implementation does not share storage with this
hierarchy.
Constructors
RingBackedCollection(IEnumerable<T>, int)
Initializes a new instance of the RingBackedCollection<T> class containing elements copied from
collection, with the specified capacity. When the source is larger than the capacity, only
the most recent capacity elements are retained.
protected RingBackedCollection(IEnumerable<T> collection, int capacity)
Parameters
collectionIEnumerable<T>The collection from which elements are copied. Must not be null.
capacityintThe backing-array capacity. Must be greater than zero.
Exceptions
- ArgumentNullException
collectionis null.- ArgumentOutOfRangeException
capacityis less than 1.
RingBackedCollection(int)
Initializes a new instance of the RingBackedCollection<T> class with a backing array of the specified capacity.
protected RingBackedCollection(int capacity)
Parameters
capacityintThe initial backing-array capacity. Must be greater than zero.
Exceptions
- ArgumentOutOfRangeException
capacityis less than 1.
Properties
Capacity
Gets the maximum number of elements that the collection can currently hold without resizing the backing array.
public int Capacity { get; }
Property Value
- int
The length of the underlying array.
Count
Gets the number of elements contained in the ICollection.
public int Count { get; }
Property Value
- int
The number of elements contained in the ICollection.
IsEmpty
Gets a value indicating whether the collection contains no elements.
public bool IsEmpty { get; }
Property Value
IsFull
Gets a value indicating whether the collection has reached the current backing-array capacity. On a fixed-capacity buffer this signals that the next add will throw or be rejected; on a growable collection it is a transient state that the next add resolves by resizing.
public bool IsFull { get; }
Property Value
this[int]
Gets the element at the specified zero-based logical index, where 0 refers to the head element.
public T this[int index] { get; }
Parameters
indexintThe zero-based, head-relative index. Must be in
[0, Count).
Property Value
- T
The element at the given logical position.
Exceptions
- ArgumentOutOfRangeException
indexis negative or not less than Count.
Methods
AddHead(T)
Adds item at the position immediately before the head and retreats the head. The caller must
ensure Count < Capacity before invoking.
protected void AddHead(T item)
Parameters
itemTThe element to prepend.
AddTail(T)
Adds item at the tail position and advances the tail. The caller must ensure
Count < Capacity before invoking.
protected void AddTail(T item)
Parameters
itemTThe element to append.
Clear()
Removes all elements from the collection, clearing the live region of the backing array and resetting head, tail, and count. Bumps the structural version when something was cleared.
public void Clear()
Exceptions
- InvalidOperationException
The method is invoked from within an eviction event handler.
Contains(T)
Determines whether the collection contains the specified element using Default.
public bool Contains(T item)
Parameters
itemTThe element to locate. May be null for reference types.
Returns
CopyTo(T[], int)
Copies the collection's elements to array in head-to-tail logical order, starting at
index.
public void CopyTo(T[] array, int index)
Parameters
arrayT[]The destination array. Must not be null.
indexintThe zero-based starting index in
array.
Exceptions
- ArgumentNullException
arrayis null.- ArgumentOutOfRangeException
indexis negative.- ArgumentException
The destination is too small to hold the contents starting at
index.
GetEnumerator()
Returns an enumerator that iterates the collection's elements in head-to-tail logical order.
public RingBackedCollection<T>.Enumerator GetEnumerator()
Returns
- RingBackedCollection<T>.Enumerator
An RingBackedCollection<T>.Enumerator for the collection.
Remarks
The enumerator captures a structural-version token at creation. Any subsequent structural mutation - including
Clear, TrimExcess, or any of the derived-type mutators - invalidates the enumerator. The next
MoveNext() or Reset() call throws
InvalidOperationException.
OverwriteTail(T)
Writes item at the slot occupied by the tail (which equals the head when the collection is
full) and advances both head and tail by one slot. Used by the eviction path of CircularBuffer<T>
when overwriting the oldest element. Count is unchanged.
protected void OverwriteTail(T item)
Parameters
itemTThe element to write into the slot occupied by the tail.
Remarks
The caller must ensure Count == Capacity before invoking.
PeekHead()
Returns the head element without removing it. The caller must ensure Count > 0.
protected T PeekHead()
Returns
- T
The current head element.
PeekTail()
Returns the tail element without removing it. The caller must ensure Count > 0.
protected T PeekTail()
Returns
- T
The element immediately preceding
_tailin modulo order.
RemoveHead()
Removes and returns the head element, clearing its slot. The caller must ensure Count > 0 before
invoking.
protected T RemoveHead()
Returns
- T
The element that was at the head.
RemoveTail()
Removes and returns the tail element, clearing its slot. The caller must ensure Count > 0 before
invoking.
protected T RemoveTail()
Returns
- T
The element that was at the tail.
Resize(int)
Replaces the backing array with one of size newCapacity, copying the live region into the
new array starting at index zero. Resets Bodu.Collections.Generic.RingBackedCollection`1._head to zero and Bodu.Collections.Generic.RingBackedCollection`1._tail to the position
just after the last element.
protected void Resize(int newCapacity)
Parameters
newCapacityintThe new capacity. Must satisfy
newCapacity >= CountandnewCapacity >= 1.
ToArray()
Returns a new array containing the collection's elements in head-to-tail logical order.
public T[] ToArray()
Returns
- T[]
A freshly allocated array of length Count.
TrimExcess()
Reduces the backing-array capacity to match Count, freeing unused memory. If the collection is empty, the capacity is reduced to one slot to keep operations valid.
public void TrimExcess()
Exceptions
- InvalidOperationException
The method is invoked from within an eviction event handler.
Explicit Interface Implementations
IEnumerable<T>.GetEnumerator()
Returns an enumerator that iterates through the collection.
IEnumerator<T> IEnumerable<T>.GetEnumerator()
Returns
- IEnumerator<T>
An enumerator that can be used to iterate through the collection.
ICollection.CopyTo(Array, int)
Copies the collection's elements to a one-dimensional Array, starting at the specified index, in head-to-tail logical order.
void ICollection.CopyTo(Array array, int index)
Parameters
arrayArrayThe destination array. Must be single-dimensional and zero-based.
indexintThe zero-based starting index in
array.
Exceptions
- ArgumentNullException
arrayis null.- ArgumentException
arrayis multidimensional, not zero-based, or has an incompatible element type.- ArgumentOutOfRangeException
indexis less than zero.
ICollection.IsSynchronized
Gets a value indicating whether access to the collection is synchronized (thread-safe). Always returns false; ring-backed collections are not thread-safe by themselves.
bool ICollection.IsSynchronized { get; }
Returns
Remarks
External synchronization is the caller's responsibility. For a thread-safe FIFO buffer, see
ConcurrentCircularBuffer<T> in the Bodu.Collections.Concurrent package.
ICollection.SyncRoot
Gets a lazily-initialized object that can be used to synchronize access to the collection.
object ICollection.SyncRoot { get; }
Returns
IEnumerable.GetEnumerator()
Returns an enumerator that iterates through a collection.
IEnumerator IEnumerable.GetEnumerator()
Returns
- IEnumerator
An IEnumerator object that can be used to iterate through the collection.
Applies to
| Product | Versions |
|---|---|
| .NET | 8, 10 |