dotnet
dotnet copied to clipboard
SpanBuilder
Overview
A StringBuilder-like api, but for spans.
API breakdown
public ref struct SpanBuilder<T>
{
Span<T> span;
int length;
public SpanBuilder(Span<T> storage) { span = storage; }
public SpanBuilder(int capacity) { span = new T[capacity]; }
public void Add(in T @value)
{
EnsureCapacity(length + 1);
span[length++] = @value;
}
public EnsureCapacity(int capacity)
{
if(span.Length >= capacity) return;
Span<T> newSpan = new T[Math.Pow(2, BitOperations.LeadingZeroCount(checked((uint)capacity)))];
span.Slice(0, length).CopyTo(newSpan);
span = newSpan;
}
public Span<T> Build(){
Span<T> built = span.Slice(0, length);
span = default;
length = default;
return built;
}
}
Usage example
// too big 😅
Breaking change?
No
Alternatives
List<T>
- causes allocation by itself (isn't a value type)
- doesn't support use of existing storage
StringBuilder
- only for strings
ValueStringBuilder
- is internal
Additional context
No response
Help us help you
Yes, I'd like to be assigned to work on this item
This is performed by the ArrayPoolBufferWriter<T>, is that not sufficient?
This is performed by the
ArrayPoolBufferWriter<T>, is that not sufficient?
It is not a value type and uses ArrayPool... Perhaps, you can prove me that I'm wrong about it?
I'm not sure I understand the use case scenario for this. The way I see it:
- If you wanted a general writer, it'd make sense to use
ArrayPoolBufferWriter<T>, so you can also reuse buffers. - If the ask is for a general writer type for a span, then I don't think the backing field should be an array at all. It should just be a writer type targeting a captured
Span<T>. I agree that that would be useful, but then the proposed API surface is not nearly sufficient. There's a related proposal for this (and for a span reader) in the runtime as well, so it might make sense to coordinate with that. I'm not entirely sure this is something we should add to the Toolkit if the goal is to get that into .NET soon. For reference, see https://github.com/dotnet/runtime/issues/23601 and https://github.com/dotnet/runtime/issues/23616. - If you're creating a span and writing to it just to return it from a method, I'd argue it's the wrong design. If you're sole owner of an array you wrote data to, you wouldn't want to return it as a span, because it makes things much clunkier for callers. If you do own the array, just return that (optionally as an
ReadOnlyMemory<T>or anImmutableArray<T>). Otherwise you're just restricting callers for no real reason, since they'd be the sole owners of that data anyway.