2015-06-07 2 views
2

Мне интересно о преимуществах использования stringbuilder, когда дело доходит до использования памяти в C#.При вызове append на stringbuilder мы добавляем строки в кучу?

Если у вас есть следующий сценарий:

var strBuilder = new StringBuilder(); 

     for(int i=0;i<1000;i++) 
     { 
      strBuilder.Append(i); /// is this not calling i.ToString(); ??? 
      strBuilder.Append(','); /// this i character comma 
      strBuilder.Append(" and "); /// this is creating a new string " and " right ? 
      strBuilder.Append(','); // this is a character comma, and not a string, this is value type 
     } 

Мой вопрос заключается в следующем: Каждый раз, когда мы вызываем метод Append, мы находимся не создает строку, которая затем используется из StringBuilder, который будет добавляться и добавлен в внутренний массив символов - буфер?

Я предполагаю, что всякий раз, когда мы добавляем что-то, мы также создаем строку, которая должна быть добавлена, а затем она сидит на куче, ожидая сбора мусора. Разве это не удар производительности для кучи?

+0

Потяните литералы за пределы петли. –

+0

Указанный код выделяет 1001 объект. При добавлении к String вместо StringBuilder вы выделите 7000 объектов. Большая разница. –

ответ

3

Мы не создаем строку, которая затем используется из stringBuilder, которая должна быть добавлена ​​и добавлена ​​во внутренний массив символов - буфер?

В вашем правильном примере да. Строка должна быть сначала выделена, а затем добавлена ​​во внутренний буфер. Но представьте, что у вас есть класс с кучей свойств, которые уже созданы, и вы хотите объединить их вместе. С помощью StringBuilder для добавления каждого из них сохраняются ненужные выделения во время конкатенации.

Я предполагаю, что всякий раз, когда мы добавляем что-то, мы также создаем строку, которая должна быть добавлена, а затем она сидит на куче, ожидая сбора мусора. Разве это не удар производительности для кучи?

Эта строка используется внутри строителя:

unsafe 
{ 
     fixed (char* valuePtr = value) 
     fixed (char* destPtr = &chunkChars[chunkLength]) 
     string.wstrcpy(destPtr, valuePtr, valueLen); 
    } 

А затем отбрасываются и eligable для коллекции. Я бы не назвал string в куче ударом производительности, но он увеличит размер кучи, в зависимости от того, сколько распределений, таких как у вас есть.

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

2

Да, новые экземпляры strings создаются каждый раз, но используется одна и та же ссылка: StringBuilder экземпляр. Только установка StringBuilder - null изменяет ссылку StringBuilder.

+0

Является ли запятая, находящаяся в стеке или куче? Я запутался здесь ... Есть ли .ToString(), вызываемый в запятой? –

+0

Мой плохой. Его параметр метода и, следовательно, будет жить в стеке. Я отредактировал ответ. – Marshal

Смежные вопросы