Вопрос по string, memory, c#, .net, stringbuilder – Как правильно использовать StringBuilder?

60

Я немного запутался в использованииStringBuilder класс, первый:

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

Но где смысл создаватьStringBuilder экземпляр, чтобы избежать создания новогоString? Это звучит как торговля "один за одним".

static void Main(string[] args)
{
    String foo = "123";
    using (StringBuilder sb = new StringBuilder(foo)) // also sb isn't disposable, so there will be error
    {
        sb.Append("456");
        foo = sb.ToString();
    }

    Console.WriteLine(foo);
    Console.ReadKey();
}

Почему я не должен просто использовать

+=

Редактировать: Хорошо, теперь я знаю, как использовать один экземплярStringBuilder (все еще не знаю, правильно ли это со стандартами кода), но это не стоит использовать только с однимstringне так ли?

@royB Что означает «состязание строк при непосредственном использовании stringbuilder (str1 + str2)»? строкаконкатенация делает на самом делене использовать StringBuilder внутри. Lasse Vågsæther Karlsen

Ваш Ответ

3   ответа
95

неизменный такие структуры, какstringЭто должно быть сделано путем копирования структуры, и тем самым, потребляя больше памяти и замедляя время выполнения приложения (также увеличиваяGC время и т.д ...).

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

Тем не мение:

при объединенииstring во время компиляции следующим образом:

string myString = "123";
myString += "234";
myString += "345";

он на самом деле скомпилируется в нечто подобное:

string myString = string.Concat("123", "234", "345");

эта функция быстрее, чем работа сStringBuilder на количествоstringВход в функцию известен.

так что для времени компиляции известноstring конкатенации вы должны предпочестьstring.Concat().

что касается неизвестного числаstring как в следующем случае:

string myString = "123";
if (Console.ReadLine() == "a")
{
    myString += "234";
}
myString += "345";

Теперь компилятор не может использоватьstring.Concat() функция, однако,StringBuilder кажется более эффективным во времени и потреблении памяти, только когда конкатенация сделана с 6-7 или большеstrings.

Неправильное использование практики:

StringBuilder myString = new StringBuilder("123");
myString.Append("234");
myString.Append("345");

Хорошая практика использования (обратите внимание, чтоif используется):

StringBuilder myString = new StringBuilder("123");
if (Console.ReadLine() == "a")
{
    myString.Append("234");
}
myString.Append("345");

Лучшая практика использования (обратите внимание, чтоwhile цикл используется):

StringBuilder myString = new StringBuilder("123");
while (Console.ReadLine() == "a")
{
    myString.Append("234"); //Average loop times 4~ or more
}
myString.Append("345");
@monster Он не будет скомпилирован вstring.Concat (между всемиstrings вList одно время), так как компилятор не может предполагать что-либо оstrings вListследовательно, если вы предполагаете, что будет больше, чем несколько конкатенаций -StringBuilder должен быть использован. Tamir Vered
@JaimieKnox обратите внимание наwhile/if и комментарий. Tamir Vered
Ах, спасибо. Я, должно быть, прочитал это 100 раз и все еще пропустил это. Jaimie Knox
Что делать, если вы объединяете вfor цикл для каждого элемента в списке? Будет+= компилировать в:string.concatenate(a,b,...,z)? Если да, то используете ли выStringBuilder если в списке ~ 4 или более элементов? monster
Разве ваши последние два примера не совпадают? Jaimie Knox
11

string являетсянеизменный класс, Вы не можете изменить его, только создать новыйstrings.

Поэтому, когда вы пишетеresult += a; у вас есть три отдельныхstrings в памяти на тот момент:aСтарая ценностьresult и новое значение. Конечно, это абсолютно нормально, если вы объединяете только ограниченное числоstrings, Если вы делаете это вfor цикл итерации по большой коллекции может стать проблемой.

StringBuilder класс предлагает улучшенную производительность в этих случаях. Вместо создания новогоstrings для хранения результата конкатенации используется тот же объект. Так что если вы используетеstringBuilder.ppend(a); у вас никогда не будет эквивалента "старого значенияresult».

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

Следует иметь в виду, что когда вам нужны промежуточные строки,StringBuilder может стать менее эффективным, так как вызов.ToString() на нем создается новая копияstring.

1

strings неизменны. При объединенииstring вы создаете новыйstring, Итак, когда вам нужно объединить многоstrings вы создаете многоobjects, Это не стоит много с точки зрения памяти, так как каждыйstring используется один раз. Но это дает дополнительную работу дляGC.

StringBuilder однако использует то же самоеobject каждый раз, но это происходит за счет простоты использования.

Похожие вопросы