Различие между строкой и StringBuilder в C#

Между чем различие string и StringBuilder?

Кроме того, каковы были бы некоторые примеры для понимания?

68
задан Peter Mortensen 26 February 2019 в 08:56
поделиться

8 ответов

Экземпляр строки неизменяем. Вы не можете изменить его после того, как он был создан. Любая операция, которая, кажется, изменяет строку, вместо этого возвращает новый экземпляр:

string foo = "Foo";
// returns a new string instance instead of changing the old one
string bar = foo.Replace('o', 'a');
string baz = foo + "bar"; // ditto here

Неизменяемые объекты обладают некоторыми хорошими свойствами, например, их можно использовать в потоках, не опасаясь проблем с синхронизацией, или что вы можете просто раздавать свои частные резервные поля напрямую, не опасаясь что кто-то изменяет объекты, которые они не должны изменять (см. массивы или изменяемые списки, которые часто необходимо скопировать, прежде чем возвращать их, если это нежелательно). Но при неосторожном использовании они могут создать серьезные проблемы с производительностью (как почти все - если вам нужен пример из языка, который гордится скоростью выполнения, посмотрите на функции C для обработки строк).

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

Простой пример: следующее заставит многих программистов съежиться от боли:

string s = string.Empty;
for (i = 0; i < 1000; i++) {
  s += i.ToString() + " ";
}

Вы в конечном итоге создадите здесь 2001 строк, 2000 из которых выброшены. Тот же пример с использованием StringBuilder:

StringBuilder sb = new StringBuilder();
for (i = 0; i < 1000; i++) {
  sb.Append(i);
  sb.Append(' ');
}

Это должно значительно снизить нагрузку на распределитель памяти: -)

Однако следует отметить, что компилятор C # достаточно умен, когда дело касается строк. Например, следующая строка

string foo = "abc" + "def" + "efg" + "hij";

будет присоединена компилятором, оставив только одну строку во время выполнения. Точно так же строки, такие как

string foo = a + b + c + d + e + f;

, будут переписаны в

string foo = string.Concat(a, b, c, d, e, f);

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

98
ответ дан 24 November 2019 в 14:16
поделиться

Строка - это неизменяемый тип. Это означает, что всякий раз, когда вы начинаете объединять строки друг с другом, вы каждый раз создаете новые строки. Если вы сделаете это так много раз, вы получите много накладных расходов к куче и риск нехватки памяти.

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

Из-за накладных расходов на создание экземпляра объекта StringBuilder в Microsoft говорят, что его полезно использовать, когда у вас более 5-10 конкатенаций строк.

Для примера кода я предлагаю вам взглянуть здесь:

0
ответ дан 24 November 2019 в 14:16
поделиться

Из документации по классу StringBuilder :

Объект String неизменяем. Каждый раз, когда вы используете один из методов класса System.String, вы создаете новый строковый объект в памяти, который требует нового выделения пространства для этого нового объекта. В ситуациях, когда вам необходимо выполнять многократные изменения строки, накладные расходы, связанные с созданием нового объекта String, могут быть дорогостоящими. Класс System.Text.StringBuilder можно использовать, если вы хотите изменить строку без создания нового объекта. Например, использование класса StringBuilder может повысить производительность при объединении множества строк в цикл.

2
ответ дан 24 November 2019 в 14:16
поделиться

StringBuilder поможет вам, когда вам нужно построить строки в несколько шагов.

Вместо этого:

String x = "";
x += "first ";
x += "second ";
x += "third ";

вы делаете

StringBuilder sb = new StringBuilder("");
sb.Append("first ");
sb.Append("second ");
sb.Append("third");
String x = sb.ToString();

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

2
ответ дан 24 November 2019 в 14:16
поделиться

Строка неизменяема, что означает, что когда вы создаете строку, вы никогда не сможете ее изменить. Вместо этого будет создана новая строка для хранения нового значения, а это может быть неэффективно, если вам нужно часто менять значение строковой переменной.

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

6
ответ дан 24 November 2019 в 14:16
поделиться

String (System.String) - это тип, определенный в .NET framework. Класс String не является изменяемым. Это означает, что каждый раз, когда вы выполняете действие над экземпляром System.String, компилятор .NET создает новый экземпляр строки. Эта операция скрыта для разработчика.

System.Text.StringBuilder - это класс, который представляет собой мутабельную строку. Этот класс предоставляет несколько полезных методов, которые позволяют пользователю управлять строкой, обернутой StringBuilder. Обратите внимание, что все манипуляции производятся над одним и тем же экземпляром StringBuilder.

Microsoft поощряет использование StringBuilder, поскольку он более эффективен с точки зрения использования памяти.

0
ответ дан 24 November 2019 в 14:16
поделиться

Также сложность конкатенации String равна O (N2), а для StringBuffer - O (N).

Таким образом, может возникнуть проблема с производительностью, когда мы используем конкатенацию в циклах, поскольку каждый раз создается много новых объектов.

0
ответ дан 24 November 2019 в 14:16
поделиться

Основное отличие:

Строка неизменяема. Это означает, что вы не можете модифицировать строку вообще; результатом модификации будет новая строка. Это неэффективно, если вы планируете добавлять к строке.

StringBuilder является изменяемым. Его можно модифицировать любым способом, и это не требует создания нового экземпляра. Когда работа завершена, для получения строки можно вызвать ToString().

Строки могут участвовать в интернировании. Это означает, что строки с одинаковым содержимым могут иметь одинаковые адреса. StringBuilder не может быть интернирован.

String - единственный класс, который может иметь литерал ссылки.

1
ответ дан 24 November 2019 в 14:16
поделиться
Другие вопросы по тегам:

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