Как меняется емкость StringBuilder?

Когда у меня пустой StringBuilder вместимостью 5 и я пишу "привет, мир!" к нему, определяет ли стандарт C # новую емкость StringBuilder? Я смутно помню, что это вдвое больше новой длины строки (чтобы избежать изменения емкости с каждой новой добавленной строкой).


person Vlad Vivdovitch    schedule 25.09.2011    source источник
comment
это не указано ни в одном стандарте, это просто деталь реализации   -  person BrokenGlass    schedule 25.09.2011
comment
StringBuilder не является частью языка C #. Это часть библиотек .net.   -  person David Heffernan    schedule 25.09.2011
comment
возможный дубликат Как StringBuilder определяет размер его емкость должна быть?   -  person bzlm    schedule 25.09.2011
comment
Что вас интересует в этой детали реализации?   -  person jason    schedule 26.09.2011
comment
@ Джейсон: Любопытный в вашем вопросе и есть ответ.   -  person Vlad Vivdovitch    schedule 26.09.2011
comment
@ Владимир Вивдович: Достаточно честно.   -  person jason    schedule 26.09.2011


Ответы (3)


Зависит от того, о какой версии .NET вы говорите. До .NET 4 StringBuilder использовал тег стандартная стратегия .NET, удваивающая емкость внутреннего буфера каждый раз, когда его нужно увеличивать.

StringBuilder был полностью переписан для .NET 4, теперь с использованием веревок. Расширение выделения теперь выполняется путем добавления еще одного отрезка веревки длиной до 8000 символов. Не так эффективен, как предыдущая стратегия, но позволяет избежать проблем с большими буферами, засоряющими кучу больших объектов. Исходный код доступен в Справочном источнике, если вы хотите познакомиться с ним поближе.

person Hans Passant    schedule 25.09.2011
comment
Когда мы обновили наш продукт с .Net 3.5 до .Net 4.5, у нас возникла путаница. Мы использовали объект построителя строк в качестве параметра для вызова собственного API через взаимодействие. Это привело к переполнению буфера, что привело к сбою процесса. Память кучи была повреждена, когда собственный API возвращал длинные строки. Мы начали предоставлять явную емкость в конструкторе, чтобы буфер мог обрабатывать длинные строки. По-видимому, он должен был раньше ломаться и для длинных строк, но об этом никогда не сообщалось. есть ли какой-то трюк в .Net 3.5, когда мы используем построитель строк в качестве буфера для собственных API-интерфейсов? - person RBT; 13.04.2016
comment
Это повреждает кучу GC в любой из версий среды выполнения. Подобное повреждение не обязательно обнаруживается, вам должно повезти. Конечно, в .NET 4 вам повезет больше - person Hans Passant; 13.04.2016

Стандарт C # не будет определять поведение класса библиотеки BCL, поскольку он не имеет ничего общего со спецификацией языка.

Насколько мне известно, фактическое поведение не определено ни в одной спецификации и зависит от реализации.

AFAIK, реализация MS удвоит емкость, как только будет достигнута текущая емкость.

См. this и это предыдущие вопросы SO.


Обновлять:

Это было изменено в .NET 4.0. как описано Гансом в его ответ. Теперь используются веревки, добавляя дополнительные 8000 символов за раз.

MSDN, однако очень осторожно указывает выяснили, что реальное поведение зависит от реализации:

StringBuilder динамически выделяет больше места, когда это необходимо, и соответственно увеличивает емкость. По соображениям производительности StringBuilder может выделять больше памяти, чем необходимо. Объем выделяемой памяти зависит от реализации.

person Oded    schedule 25.09.2011
comment
Мы больше не используем стратегию «двойное при заполнении». - person Eric Lippert; 25.09.2011
comment
@Eric - Спасибо, что поправили меня. Это и ответ Ганса дали мне более подробную информацию. - person Oded; 26.09.2011

Новый StringBuilder (.NET 4.5 или выше) выделяет внутренний буфер m_ChunkChars, запрошенный параметром емкости:

public StringBuilder(int capacity) { ... m_ChunkChars = new char[capacity]; ... }

Таким образом, если емкость меньше 40 КБ, она попадает в кучу малых объектов. Однако (вопреки распространенному мнению) StringBuilder по-прежнему будет выделять память в куче больших объектов, если позже мы вызовем sb.Append(...some string larger than 40K chars...);. Возможное исправление можно найти здесь: https://github.com/amikunov/Large-Object-Heap-Fix-For-.NET-String-Builder

person AlexM    schedule 18.05.2017
comment
Это не имеет ничего общего с тем, о чем задается вопрос. - person Servy; 18.05.2017