В чем разница между изменяемой и неизменяемой строкой в С#?
В чем разница между изменяемой и неизменяемой строкой в С#?
Ответ 1
Переменные и неизменные - английские слова, означающие "can change" и "can not change" соответственно. Смысл слов в ИТ-контексте одинаковый; то есть.
- измененная строка может быть изменена и
- неизменяемая строка не может быть изменена.
Значения этих слов одинаковы в С#/.NET, как в других языках/средах программирования, хотя (очевидно) имена типов могут отличаться, как и другие детали.
Для записи:
-
String
является стандартным строковым типом С#/.Net -
StringBuilder
является стандартным типом изменяемой строки С#/.Net
Чтобы "произвести изменение" в строке, представленной как С# String
, вы фактически создаете новый объект String
. Оригинал String
не изменяется... потому что он неизменен.
В большинстве случаев лучше использовать String
, потому что это более простой разум о них; например вам не нужно учитывать возможность того, что какой-то другой поток может "изменить мою строку". Однако, когда вам нужно построить или изменить строку, используя последовательность операций, может быть более эффективным использование StringBuilder
.
Ответ 2
String
является неизменным
то есть. строки не могут быть изменены. Когда вы изменяете строку (например, добавляя к ней), вы на самом деле создаете новую строку.
Но StringBuilder
не является неизменным (скорее, он изменен)
поэтому, если вам нужно много раз менять строку, например несколько конкатенаций, используйте StringBuilder
.
Ответ 3
Объект изменен, если после его создания его состояние можно изменить, вызвав на него различные операции, в противном случае оно будет неизменным.
Неизменяемая строка
В С# (и .NET) строка представлена классом System.String. Ключевое слово string
является псевдонимом для этого класса.
Класс System.String неизменен, т.е. когда его созданное состояние не может быть изменено.
Таким образом, все операции, которые вы выполняете в строке типа Substring, Remove, Replace, concatenation с помощью оператора "+" и т.д., создадут новую строку и вернете ее.
См. следующую программу демонстрации -
string str = "mystring";
string newString = str.Substring(3);
Console.WriteLine(newString);
Console.WriteLine(str);
Это будет печатать 'string' и 'mystring' соответственно.
Для преимуществ неизменяемости и почему строка неизменяема. Почему .NET String неизменна?.
Mutable String
Если вы хотите иметь строку, которую вы хотите часто изменять, вы можете использовать класс StringBuilder
. Операции над экземпляром StringBuilder
будут изменять один и тот же объект.
Дополнительные советы по , когда использовать StringBuilder
см. Когда использовать StringBuilder?.
Ответ 4
Все объекты string
неизменяемы в С#. Объекты класса string
, после создания, никогда не могут представлять какое-либо значение, отличное от того, с которым они были построены. Все операции, которые, похоже, "меняют" строку, вместо этого создают новую. Это неэффективно с памятью, но чрезвычайно полезно для того, чтобы быть уверенным в том, что строка не изменит форму под вас - поскольку до тех пор, пока вы не измените свою ссылку, строка, на которую ссылается, никогда не изменится.
У изменяемого объекта, напротив, есть поля данных, которые можно изменить. Один или несколько из его методов изменят содержимое объекта или у него есть свойство, которое при записи на него изменит значение объекта.
Если у вас есть изменяемый объект - наиболее похожий на String - StringBuffer
- тогда вы должны сделать его копию, если хотите быть абсолютно уверенным, что он не изменится из-под вас. Вот почему изменяемые объекты опасны для использования в качестве ключей в любой форме Dictionary
или set - сами объекты могут измениться, а структура данных не будет знать, что приведет к повреждению данных, которые в конечном итоге могут привести к сбою вашей программы.
Тем не менее, вы можете изменить его содержимое, поэтому он намного эффективнее памяти, чем полная копия, потому что вы хотели изменить один символ или что-то подобное.
Как правило, правильная вещь - использовать изменяемые объекты, пока вы что-то создаете, и неизменяемые объекты, как только вы закончите. Это относится, конечно, к объектам, которые имеют неизменные формы; большинство коллекций этого не делают. Тем не менее часто бывает полезно предоставлять только коллекции только для чтения, но это эквивалентно неизменяемости при отправке внутреннего состояния вашей коллекции в другие контексты. В противном случае что-то может взять это возвращаемое значение, что-то сделать, и испортить ваши данных.
Ответ 5
Неизменяемость:
Когда вы выполняете некоторую операцию над объектом, он создает новый объект, поэтому состояние не модифицируется, как в случае строки.
Mutable
Когда вы выполняете некоторую операцию над объектом, сам объект не изменил никакого нового объекта, созданного как в случае StringBuilder
Ответ 6
В .NET System.String(aka string) - неизменяемый объект. Это означает, что когда вы создаете объект, вы не можете впоследствии изменить его значение. Вы можете воссоздать неизменяемый объект.
System.Text.StringBuilder является изменяемым эквивалентом System.String, и вы можете использовать его значение
Пример:
class Program
{
static void Main(string[] args)
{
System.String str = "inital value";
str = "\nsecond value";
str = "\nthird value";
StringBuilder sb = new StringBuilder();
sb.Append("initial value");
sb.AppendLine("second value");
sb.AppendLine("third value");
}
}
Создает следующий MSIL: Если вы исследуете код. Вы увидите, что всякий раз, когда вы производите объект System.String, вы на самом деле создаете новый. Но в System.Text.StringBuilder всякий раз, когда вы меняете значение текста, вы не воссоздаете объект.
.method private hidebysig static void Main(string[] args) cil managed
{
.entrypoint
// Code size 62 (0x3e)
.maxstack 2
.locals init ([0] string str,
[1] class [mscorlib]System.Text.StringBuilder sb)
IL_0000: nop
IL_0001: ldstr "inital value"
IL_0006: stloc.0
IL_0007: ldstr "\nsecond value"
IL_000c: stloc.0
IL_000d: ldstr "\nthird value"
IL_0012: stloc.0
IL_0013: newobj instance void [mscorlib]System.Text.StringBuilder::.ctor()
IL_0018: stloc.1
IL_0019: ldloc.1
IL_001a: ldstr "initial value"
IL_001f: callvirt instance class [mscorlib]System.Text.StringBuilder [mscorlib]System.Text.StringBuilder::Append(string)
IL_0024: pop
IL_0025: ldloc.1
IL_0026: ldstr "second value"
IL_002b: callvirt instance class [mscorlib]System.Text.StringBuilder [mscorlib]System.Text.StringBuilder::AppendLine(string)
IL_0030: pop
IL_0031: ldloc.1
IL_0032: ldstr "third value"
IL_0037: callvirt instance class [mscorlib]System.Text.StringBuilder [mscorlib]System.Text.StringBuilder::AppendLine(string)
IL_003c: pop
IL_003d: ret
} // end of method Program::Main
Ответ 7
Строки изменяемы, потому что .NET использует пул строк за сценой. Это означает:
string name = "My Country";
string name2 = "My Country";
И имя, и имя2 относятся к тому же месту памяти из пула строк. Теперь предположим, что вы хотите изменить имя2 на:
name2 = "My Loving Country";
Он будет выглядеть в пуле строк для строки "My Loving Country", если вы найдете ее, вы получите ссылку на другую новую новую строку "My Loving Country" будет создана в пуле строк, а name2 получит ссылку на нее, Но весь этот процесс " Моя страна" не был изменен, поскольку по-прежнему используется другая переменная типа name. И именно поэтому строка IMMUTABLE.
StringBuilder работает по-разному и не использует пул строк. Когда мы создаем любой экземпляр StringBuilder:
var address = new StringBuilder(500);
Он выделяет кусок памяти размером 500 байт для этого экземпляра, и вся операция просто изменяет эту ячейку памяти, и эта память не используется совместно с каким-либо другим объектом. И вот почему StringBuilder MUTABLE.
Надеюсь, это поможет.
Ответ 8
Нет, на самом деле. Класс String является изменяемым.
unsafe
{
string foo = string.Copy("I am immutable.");
fixed (char* pChar = foo)
{
char* pFoo = pChar;
pFoo[5] = ' ';
pFoo[6] = ' ';
}
Console.WriteLine(foo); // "I am mutable."
}
Этот тип логики выполняется все время в классах String и StringBuilder. Они просто выделяют новую строку каждый раз, когда вы вызываете Concat, Substring и т.д. И используете арифметику указателя для копирования в новую строку. Строки просто не мутируют себя, поэтому почему они считаются "неизменными".
Кстати, do not попытайтесь это с помощью строковых литералов или вы плохо испортите свою программу:
string bar = "I am a string.";
fixed (char* pChar = bar)
{
char* pBar = pChar;
pBar[2] = ' ';
}
string baz = "I am a string.";
Console.WriteLine(baz); // "I m a string."
Это связано с тем, что строковые литералы интернированы на рабочем столе .NET Framework; другими словами, bar
и baz
указывают на одну и ту же строку, поэтому мутирующий один будет мутировать другой. Это все прекрасно и денди, хотя, если вы используете неуправляемую платформу, такую как WinRT, которой не хватает интернирования строк.
Ответ 9
Чтобы прояснить, в С# (или вообще .NET) нет такой вещи, как изменяемая строка. Другие языки поддерживают изменяемые строки (строка, которая может меняться), но .NET Framework не делает.
Итак, правильный ответ на ваш вопрос: ВСЕ строка неизменяема в С#.
Строкаимеет определенное значение. "Строковое" ключевое слово нижнего регистра - это просто ярлык для объекта, созданного из класса System.String. Все объекты, созданные из класса string, ВСЕГДА неизменяемы.
Если вы хотите изменить представление текста, вам нужно использовать другой класс, например StringBuilder. StringBuilder позволяет вам итеративно создавать коллекцию "слов", а затем преобразовывать ее в строку (еще раз неизменяемую).
Ответ 10
в деталях реализации.
CLR2 System.String является muttable. StringBuilder.Append вызывает String.AppendInplace(частный метод)
CLR4 System.String imuttable. У StringBuilder есть массив Char с блоком.
Ответ 11
Значение данных не может быть изменено. Примечание. Значение переменной может быть изменено, но исходное неизменяемое значение данных было отброшено и в памяти было создано новое значение данных.
Ответ 12
Строки неизменяемы, что означает, что мы каждый раз выделяем новую память вместо работы с существующей строкой.
Строки создаются в пуле. Если строка уже существует, она просто ее не создает.
for (int i = 0; i < 1000; i++)
{
str += "Modified ";
}
StringBuilder - это изменяемый тип, это означает, что мы используем одно и то же место в памяти и продолжаем добавлять/модифицировать материал в один экземпляр. Он не будет создавать никаких дополнительных экземпляров, поэтому он не снизит производительность приложения.
for (int i = 0; i < 10000; i++)
{
strB.Append("Modified ");
}
Ответ 13
Из http://yassershaikh.com/what-is-the-difference-between-strings-and-stringbuilder-in-c-net/
Короткий ответ: Строка неизменна, тогда как StringBuilder изменен.
Что это значит? Wiki говорит: В объектно-ориентированном неизменяемом объекте есть объект, состояние которого не может быть изменено после его создания. Это отличается от изменяемого объекта, который может быть изменен после его создания.
Из документации класса StringBuilder:
Объект String неизменен. Каждый раз, когда вы используете один из методов в классе System.String, вы создаете новый строковый объект в памяти, для которого требуется новое выделение пространства для этого нового объекта.
В ситуациях, когда вам необходимо выполнить повторные модификации строки, служебные данные, связанные с созданием нового объекта String, могут быть дорогостоящими.
Класс System.Text.StringBuilder может использоваться, когда вы хотите изменить строку без создания нового объекта. Например, использование класса StringBuilder может повысить производительность при объединении многих строк в цикл.
Ответ 14
Вот пример для неизменяемой строки и Mutable string builder
Console.WriteLine("Mutable String Builder");
Console.WriteLine("....................................");
Console.WriteLine();
StringBuilder sb = new StringBuilder("Very Good Morning");
Console.WriteLine(sb.ToString());
sb.Remove(0, 5);
Console.WriteLine(sb.ToString());
Console.WriteLine();
Console.WriteLine("Immutable String");
Console.WriteLine("....................................");
Console.WriteLine();
string s = "Very Good Morning";
Console.WriteLine(s);
s.Substring(0, 5);
Console.WriteLine(s);
Console.ReadLine();
Ответ 15
Строка в С# неизменна. Если вы соедините его с любой строкой, вы на самом деле создаете новую строку, то есть новый строковый объект! Но StringBuilder создает изменяемую строку.