Open JeremyKuhne opened 6 years ago
Anything slated for language changes to allow this? I think forcing ref structs makes sense as a new language construct.
Will it come out in 6.0.0?
For now I exposed my own by essentially shamelessly copying it: https://github.com/modernuo/ModernUO/blob/main/Projects/Server/Buffers/ValueStringBuilder.cs
Also you can use https://github.com/Cysharp/ZString which has a great StringBuilder-like API.
This is essentially blocked on resolving discussion in https://github.com/dotnet/runtime/issues/50389.
Since roslyn adds support for utf8 strings handled as ReadOnlySpan<byte>
, i think it will be better to have something like ValueSpanBuilder<T>
instead.
Has been anything further done in this regard, i ask out of curiosity
ValueStringBuilder
is in runtime now, as I can see: https://github.com/dotnet/runtime/blob/main/src/libraries/Common/src/System/Text/ValueStringBuilder.cs
but not public for some reason. what is that reason? public ValueStringBuilder
is the key to provide, for example, global::System.Net.WebUtility.HtmlDecode(ReadOnlySpan<char>)
into the public space.
but not public for some reason. what is that reason?
https://github.com/dotnet/runtime/issues/25587#issuecomment-525424732
Just saw another copy of this type pop up, and see that we currently have 20+ copies in the product. https://source.dot.net/#q=ValueStringBuilder
Is there any progress on the language feature that would make us comfortable exposing this type?
and see that we currently have 20+ copies in the product
To clarify (I'm not sure if this is what you meant or not), we have that many in binaries, not that many source copies, with the same source built as internal into many places.
We should consider making a value based StringBuilder to allow low allocation building of strings. While Span allows you to provide a writable buffer, in many scenarios we have a need to get or build strings and we don't know precisely how much space will be needed ahead of time. Having an abstraction that can grow beyond a given initial buffer is particularly useful as it doesn't require looping with
Try*
APIs- which can be both complicated and have negative performance implications.We currently use if needed.
ValueStringBuilder
for this purpose internally. It starts with an optional initial buffer (which we often stackalloc) and will grow using ArrayPoolDesign Goals
char* szValue
)API
Here is the proposed API:
This is the current shape of our internal
ValueStringBuilder
:Sample Code
Here is a common pattern on an API that could theoretically be made public if ValueStringBuilder was public: (Although we would call this one GetFullUserName or something like that.)
https://github.com/dotnet/corefx/blob/050bc33738887d9d8fcc9bc5965b7d9ca65bc7f4/src/System.Runtime.Extensions/src/System/Environment.Win32.cs#L40-L56
The caller is above this method:
https://github.com/dotnet/corefx/blob/050bc33738887d9d8fcc9bc5965b7d9ca65bc7f4/src/System.Runtime.Extensions/src/System/Environment.Win32.cs#L13-L38
Usage of AppendSpan:
https://github.com/dotnet/corefx/blob/3538128fa1fb2b77a81026934d61cd370a0fd7f5/src/System.Runtime.Numerics/src/System/Numerics/BigNumber.cs#L550-L560
I'll add more usage details and possible API surface area.
Notes
bool TryGet*(Span)
overload? (see https://github.com/dotnet/coreclr/pull/17097/files#r176560435)Dispose()
in ausing
statement? (https://github.com/dotnet/csharplang/issues/93)AppendFormat
overloads?AppendSpan()
is a little tricky to grok- is there a better term/pattern?