PooledBufferBuilder<T> Class
Definition
Provides an efficient way to accumulate elements into a pooled buffer, with automatic resizing and fast-path optimizations for collection-based and span-based sources.
public sealed class PooledBufferBuilder<T> : IBufferWriter<T>, IMemoryOwner<T>, IDisposable
Type Parameters
TThe type of elements to buffer.
- Inheritance
-
PooledBufferBuilder<T>
- Implements
-
IMemoryOwner<T>
- Inherited Members
- Extension Methods
Examples
// Accumulate a result of unknown length without per-item array doubling.
using var builder = new PooledBufferBuilder<int>(initialCapacity: 256);
foreach (int value in source)
builder.Append(value);
ReadOnlySpan<int> span = builder.WrittenSpan;
Console.WriteLine($"Buffered {builder.WrittenCount} values from a pooled buffer of {builder.Capacity}.");
// The rented array is returned to ArrayPool<int>.Shared when 'builder' is disposed.
Remarks
Buffers are rented from Shared and returned on Dispose(). When
T is a reference type or contains references, the live portion of the buffer is cleared
before the underlying array is returned to the pool, preventing unintended object retention.
Call Reset() to clear accumulated data and reuse the current rented buffer without a pool round-trip. Call Dispose() when the builder is no longer needed.
Constructors
PooledBufferBuilder(int)
Initializes a new instance of the PooledBufferBuilder<T> class with the specified initial capacity.
public PooledBufferBuilder(int initialCapacity = 256)
Parameters
initialCapacityintThe minimum initial capacity of the pooled buffer. Must be greater than zero. Defaults to 256.
Exceptions
- ArgumentOutOfRangeException
Thrown when
initialCapacityis less than 1.
Properties
Capacity
Gets the current capacity of the internal buffer.
public int Capacity { get; }
Property Value
- int
The length of the underlying rented array. This value is always greater than or equal to WrittenCount and may be larger than the capacity requested at construction due to ArrayPool<T> rounding behavior.
Exceptions
- ObjectDisposedException
Thrown if the instance has been disposed.
FreeCapacity
Gets the number of elements that can be written to the buffer before the next growth.
public int FreeCapacity { get; }
Property Value
- int
The number of remaining slots in the current rented array - equivalent to Capacity minus WrittenCount.
Exceptions
- ObjectDisposedException
Thrown if the instance has been disposed.
IsEmpty
Gets a value indicating whether no elements have been written to the buffer.
public bool IsEmpty { get; }
Property Value
- bool
true if WrittenCount is zero; otherwise false.
Exceptions
- ObjectDisposedException
Thrown if the instance has been disposed.
WrittenCount
Gets the number of elements that have been written to the buffer.
public int WrittenCount { get; }
Property Value
Exceptions
- ObjectDisposedException
Thrown if the instance has been disposed.
WrittenMemory
Gets a ReadOnlyMemory<T> representing the elements written to the buffer.
public ReadOnlyMemory<T> WrittenMemory { get; }
Property Value
- ReadOnlyMemory<T>
A ReadOnlyMemory<T> containing exactly the first WrittenCount buffered elements.
Exceptions
- ObjectDisposedException
Thrown if the instance has been disposed.
WrittenSpan
Gets a ReadOnlySpan<T> representing the elements written to the buffer.
public ReadOnlySpan<T> WrittenSpan { get; }
Property Value
- ReadOnlySpan<T>
A ReadOnlySpan<T> containing exactly the first WrittenCount buffered elements.
Exceptions
- ObjectDisposedException
Thrown if the instance has been disposed.
Methods
AddMany(T, int)
Appends count copies of value to the buffer, growing the internal array
if necessary.
public void AddMany(T value, int count)
Parameters
valueTThe value to repeat.
countintThe number of times to append
value. Must be non-negative.
Exceptions
- ArgumentOutOfRangeException
Thrown when
countis negative.- ObjectDisposedException
Thrown if the instance has been disposed.
Advance(int)
Notifies the builder that count elements were written into the span or memory most recently
returned by GetSpan(int) or GetMemory(int).
public void Advance(int count)
Parameters
countintThe number of elements written. Must be non-negative and must not exceed the length of the buffer most recently returned by GetSpan(int) or GetMemory(int).
Exceptions
- ArgumentOutOfRangeException
Thrown when
countis negative or would advance WrittenCount past the end of the current internal buffer.- ObjectDisposedException
Thrown if the instance has been disposed.
Append(T)
Appends a single element to the buffer, growing the internal array if necessary.
public void Append(T item)
Parameters
itemTThe element to append.
Exceptions
- ObjectDisposedException
Thrown if the instance has been disposed.
AppendRange(IEnumerable<T>)
Appends a sequence of elements from the specified IEnumerable<T> source, growing the buffer as needed.
public void AppendRange(IEnumerable<T> source)
Parameters
sourceIEnumerable<T>The sequence of elements to append. Must not be null.
Remarks
When source implements ICollection<T>, a single bulk copy is performed
instead of element-by-element iteration.
Exceptions
- ArgumentNullException
Thrown if
sourceis null.- ObjectDisposedException
Thrown if the instance has been disposed.
AppendRange(ReadOnlyMemory<T>)
Appends all elements from the specified ReadOnlyMemory<T> to the buffer, growing the internal array if necessary.
public void AppendRange(ReadOnlyMemory<T> source)
Parameters
sourceReadOnlyMemory<T>The memory region of elements to append.
Exceptions
- ObjectDisposedException
Thrown if the instance has been disposed.
AppendRange(ReadOnlySpan<T>)
Appends all elements from the specified ReadOnlySpan<T> to the buffer, growing the internal array if necessary.
public void AppendRange(ReadOnlySpan<T> source)
Parameters
sourceReadOnlySpan<T>The span of elements to append.
Remarks
source may alias the builder's own storage (for example a span obtained from
WrittenSpan or DangerousGetArray()): when a growth is required, the previous rented
array is returned to the pool only after the source elements have been copied, so a self-aliasing source remains
valid throughout the append.
Exceptions
- ObjectDisposedException
Thrown if the instance has been disposed.
CopyTo(Span<T>)
Copies the written elements into destination.
public void CopyTo(Span<T> destination)
Parameters
destinationSpan<T>The target span. Must be at least WrittenCount elements long.
Exceptions
- ArgumentException
Thrown when
destinationis too small.- ObjectDisposedException
Thrown if the instance has been disposed.
DangerousGetArray()
Returns an ArraySegment<T> that aliases the underlying rented array, bounded to the written region.
public ArraySegment<T> DangerousGetArray()
Returns
- ArraySegment<T>
An ArraySegment<T> starting at offset 0 with a count equal to WrittenCount. The segment points directly into pooled memory and must not be used after Dispose() is called.
Remarks
This method is an escape hatch for APIs that require a byte[] or ArraySegment<T> rather
than a Span<T> or Memory<T>. Treat the returned segment as borrowed - do not
retain it beyond the lifetime of this builder.
Exceptions
- ObjectDisposedException
Thrown if the instance has been disposed.
Dispose()
Releases the pooled buffer and resets the internal state of the builder.
public void Dispose()
Remarks
After calling this method, further operations on the instance will throw ObjectDisposedException.
EnsureCapacity(int)
Ensures the internal buffer can hold at least minimum elements, growing via a new pooled
allocation when needed.
public void EnsureCapacity(int minimum)
Parameters
minimumintThe minimum total capacity required. Must be non-negative. No-ops when the current Capacity already satisfies the request.
Exceptions
- ArgumentOutOfRangeException
Thrown when
minimumis negative.- ObjectDisposedException
Thrown if the instance has been disposed.
GetMemory(int)
Returns a Memory<T> of at least sizeHint elements into which the caller can
write, automatically growing the buffer if necessary.
public Memory<T> GetMemory(int sizeHint = 0)
Parameters
sizeHintintThe minimum number of elements required. When zero or negative, at least one element of free space is ensured. The returned memory may be larger than the hint.
Returns
- Memory<T>
A writable Memory<T> beginning at the current write position and spanning all free capacity. Call Advance(int) after writing to commit the data.
Exceptions
- ArgumentOutOfRangeException
Thrown when
sizeHintis negative.- ObjectDisposedException
Thrown if the instance has been disposed.
GetSpan(int)
Returns a Span<T> of at least sizeHint elements into which the caller can
write, automatically growing the buffer if necessary.
public Span<T> GetSpan(int sizeHint = 0)
Parameters
sizeHintintThe minimum number of elements required. When zero or negative, at least one element of free space is ensured. The returned span may be larger than the hint.
Returns
- Span<T>
A writable Span<T> beginning at the current write position and spanning all free capacity. Call Advance(int) after writing to commit the data.
Exceptions
- ArgumentOutOfRangeException
Thrown when
sizeHintis negative.- ObjectDisposedException
Thrown if the instance has been disposed.
Reset()
Resets the builder to an empty state, retaining the current rented buffer to avoid a pool round-trip.
public void Reset()
Remarks
Any reference slots in the valid portion of the buffer are cleared to prevent unintended object retention. The underlying array is not returned to Shared; call Dispose() to release it.
Exceptions
- ObjectDisposedException
Thrown if the instance has been disposed.
Sort(IComparer<T>?)
Sorts the written elements in place using the specified comparer, or the default comparer when
comparer is null.
public void Sort(IComparer<T>? comparer = null)
Parameters
Exceptions
- ObjectDisposedException
Thrown if the instance has been disposed.
Sort(Comparison<T>)
Sorts the written elements in place using the specified comparison delegate.
public void Sort(Comparison<T> comparison)
Parameters
comparisonComparison<T>The comparison to use. Must not be null.
Exceptions
- ArgumentNullException
Thrown when
comparisonis null.- ObjectDisposedException
Thrown if the instance has been disposed.
ToArrayAndDispose()
Copies the written elements into a freshly allocated array and disposes the builder in a single call.
public T[] ToArrayAndDispose()
Returns
- T[]
A new array of length WrittenCount containing the written elements in order. The returned array is owned by the caller and is independent of any pooled storage.
Remarks
This is the canonical "build, materialize, release" shortcut for callers that want a managed array and do not need to continue mutating the builder. After this call returns, the builder is disposed and any further operation on it throws ObjectDisposedException.
Exceptions
- ObjectDisposedException
Thrown if the instance has already been disposed.
TryCopyFrom(IReadOnlyCollection<T>)
Attempts to populate the buffer from the specified IReadOnlyCollection<T> using a fast-path
CopyTo when the source also implements ICollection<T>.
public bool TryCopyFrom(IReadOnlyCollection<T> source)
Parameters
sourceIReadOnlyCollection<T>The source collection to copy from. Must not be null.
Returns
- bool
true if the copy was performed via CopyTo(T[], int); false if the source does not implement ICollection<T> and no copy was performed.
Remarks
When successful, any previously buffered data is discarded and replaced with the contents of
source. The current rented array is reused when its capacity is sufficient, and
WrittenCount is set to the source element count.
Exceptions
- ArgumentNullException
Thrown if
sourceis null.- ObjectDisposedException
Thrown if the instance has been disposed.
TryCopyTo(Span<T>)
Attempts to copy the written elements into destination without throwing when the destination
is too small.
public bool TryCopyTo(Span<T> destination)
Parameters
destinationSpan<T>The target span to copy into.
Returns
- bool
true when
destinationhas space for at least WrittenCount elements and the copy was performed; false when the destination is too small, in which case nothing is written.
Remarks
Use this overload in code paths that probe the destination size and act on the boolean rather than catching ArgumentException from CopyTo(Span<T>).
Exceptions
- ObjectDisposedException
Thrown if the instance has been disposed.
Explicit Interface Implementations
IMemoryOwner<T>.Memory
Gets the written region of the buffer as a Memory<T>, as required by IMemoryOwner<T>.
Memory<T> IMemoryOwner<T>.Memory { get; }
Returns
- Memory<T>
A Memory<T> covering exactly the first WrittenCount elements.
Exceptions
- ObjectDisposedException
Thrown if the instance has been disposed.
Applies to
| Product | Versions |
|---|---|
| .NET | 8, 10 |