Репост из: C# Heppard
Напоминаю про чудесный ValueStringBuilder, который находится в недрах DotNet и является internal. Идеальня вещь для замены StringBuilder. Когда я на собеседованиях спрашиваю про то, как создать строку, то я считаю ответ про StringBuilder правильным, но на 4. Ответ на 5 - ValueStringBuilder.
Про него не рассказывал только ленивый, но я ещё раз про него расскажу.
Штука до боли простая - это ref struct, которая принимает в конструктор Span. Обычно его создают на стеке путём stackallock char[256]. Если в процессе создания строки выяснятся, что переданного Span не хватает - создаётся честный массив из ArrayPool.
internal ref partial struct ValueStringBuilder {
private char[]? _arrayToReturnToPool;
private Span _chars;
private int _pos;
public ValueStringBuilder(Span initialBuffer)
{
_arrayToReturnToPool = null;
_chars = initialBuffer;
_pos = 0;
}
...
private void Grow(int additionalCapacityBeyondPos)
{
int newCapacity = _pos + additionalCapacityBeyondPos);
char[] poolArray = ArrayPool.Shared.Rent(newCapacity);
...
}
Далее вы можете добавлять работать с ValueStringBuilder'ом так, будто это обычный StringBuilder - у них очень похожие API. Штука специальная, но идеально подходит под создание коротких строк без всякой аллокации. Единственное, нужно всегда помнить о том, что stack, на котором мы создаём Span, не резиновый. Это значит, что создавая первоначальный буффер размером в 1024 символа мы несколько рискуем.
Однако, иногда риск оправдан и ValueStringBuilder значительно экономит память.
#память
Про него не рассказывал только ленивый, но я ещё раз про него расскажу.
Штука до боли простая - это ref struct, которая принимает в конструктор Span. Обычно его создают на стеке путём stackallock char[256]. Если в процессе создания строки выяснятся, что переданного Span не хватает - создаётся честный массив из ArrayPool.
internal ref partial struct ValueStringBuilder {
private char[]? _arrayToReturnToPool;
private Span _chars;
private int _pos;
public ValueStringBuilder(Span initialBuffer)
{
_arrayToReturnToPool = null;
_chars = initialBuffer;
_pos = 0;
}
...
private void Grow(int additionalCapacityBeyondPos)
{
int newCapacity = _pos + additionalCapacityBeyondPos);
char[] poolArray = ArrayPool.Shared.Rent(newCapacity);
...
}
Далее вы можете добавлять работать с ValueStringBuilder'ом так, будто это обычный StringBuilder - у них очень похожие API. Штука специальная, но идеально подходит под создание коротких строк без всякой аллокации. Единственное, нужно всегда помнить о том, что stack, на котором мы создаём Span, не резиновый. Это значит, что создавая первоначальный буффер размером в 1024 символа мы несколько рискуем.
Однако, иногда риск оправдан и ValueStringBuilder значительно экономит память.
#память