В чем разница между изменяемой и неизменной строкой в C #?
В чем разница между изменяемой и неизменной строкой в C #?
Ответы:
Изменчивые и неизменные - это английские слова, означающие «может измениться» и «не может измениться» соответственно. Значение слов одинаково в контексте ИТ; т.е.
Значения этих слов в C # / .NET такие же, как и в других языках программирования / средах, хотя (очевидно) имена типов могут отличаться, как и другие детали.
Для записи:
String
является стандартным неизменяемым строковым типом C # / .Net StringBuilder
стандартный тип изменяемой строки C # / .Net Чтобы «внести изменения» в строку, представленную как C # String
, вы фактически создаете новый String
объект. Оригинал String
не изменился ... потому что он неизменен.
В большинстве случаев это лучше использовать, String
потому что это более легкая причина для них; Например, вам не нужно учитывать возможность того, что какой-то другой поток может «изменить мою строку». Однако, когда вам нужно создать или изменить строку, используя последовательность операций, может быть более эффективно использовать a StringBuilder
.
И, наконец, для тех людей, которые утверждают, что a StringBuilder
не является строкой, потому что она не является неизменной, документация Microsoft описывает StringBuilder
так:
"Представляет изменяемую строку символов. Этот класс не может быть унаследован."
String
неизменен
т.е. строки не могут быть изменены. Когда вы изменяете строку (например, добавляя ее), вы фактически создаете новую строку.
Но StringBuilder
не является неизменным (скорее, оно изменчиво)
так что если вам нужно многократно изменять строку, например, несколько конкатенаций, используйте StringBuilder
.
O(N^2)
поведению ...
Объект является изменяемым, если однажды созданный объект может быть изменен путем вызова различных операций с ним, в противном случае он является неизменным.
В C # (и .NET) строка представлена классом System.String. string
Ключевым словом является псевдонимом для этого класса.
Класс System.String является неизменным, т.е. после создания его состояние не может быть изменено .
Таким образом , все операции вы выполняете на строке , как Substring
, Remove
, Replace
, конкатенации с помощью оператора «+» и т.д. создаст новую строку и вернуть его.
Смотрите следующую программу для демонстрации -
string str = "mystring";
string newString = str.Substring(2);
Console.WriteLine(newString);
Console.WriteLine(str);
Это выведет «string» и «mystring» соответственно.
Для преимуществ неизменности и почему строка неизменна проверка Почему .NET Строка неизмененна? ,
Если вы хотите иметь строку, которую хотите часто изменять, вы можете использовать StringBuilder
класс. Операции над StringBuilder
экземпляром изменят тот же объект .
Для получения более подробной консультации по когда использовать StringBuilder
смотрите Когда использовать StringBuilder? ,
Все string
объекты неизменны в C #. string
Созданные объекты класса никогда не могут представлять ничего, кроме того, с которым они были созданы. Все операции, которые, кажется, «изменяют» строку, вместо этого производят новую. Это неэффективно с памятью, но чрезвычайно полезно для уверенности в том, что строка не изменит форму под вами - потому что, пока вы не измените свою ссылку, строка, на которую вы ссылаетесь, никогда не изменится.
У изменчивого объекта, напротив, есть поля данных, которые можно изменить. Один или несколько его методов изменят содержимое объекта, или у него есть свойство, которое при записи изменяет значение объекта.
Если у вас есть изменяемый объект, наиболее похожий на String, StringBuffer
вы должны сделать его копию, если хотите быть абсолютно уверенным, что он не изменится из-под вас. Вот почему изменяемые объекты опасны для использования в качестве ключей в любой форме Dictionary
или для установки - сами объекты могут измениться, и структура данных не сможет узнать, что приведет к повреждению данных, что в конечном итоге приведет к сбою вашей программы.
Тем не менее, вы можете изменить его содержимое, так что это намного, намного более эффективно использует память, чем создание полной копии, потому что вы хотели изменить один символ или что-то подобное.
Как правило, правильнее всего использовать изменяемые объекты при создании чего-либо и неизменные объекты после завершения работы. Конечно, это относится к объектам, которые имеют неизменные формы; большинство коллекций этого не делают. Часто бывает полезно предоставлять формы коллекций только для чтения, что эквивалентно неизменяемости при отправке внутреннего состояния вашей коллекции в другие контексты - в противном случае что-то может принять это возвращаемое значение, что-то с ним сделать и испортить вашу данные.
Неизменный :
Когда вы выполняете какую-либо операцию над объектом, он создает новый объект, следовательно, состояние не может быть изменено, как в случае строки.
изменчивый
Когда вы выполняете какую-либо операцию над объектом, сам объект не изменял созданный новый объект, как в случае StringBuilder
В .NET System.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
Строки являются изменяемыми, потому что .NET используют пул строк за сценой. Это значит :
string name = "My Country";
string name2 = "My Country";
И имя, и имя2 ссылаются на одну и ту же область памяти из пула строк. Теперь предположим, что вы хотите изменить name2 на:
name2 = "My Loving Country";
Он будет искать в строковом пуле строку «Моя любящая страна», если найден, вы получите ссылку на нее, в мудром пуле будет создана новая мудрая строка «Моя любящая страна», а name2 получит ссылку на нее. Но весь этот процесс « Моя страна » не изменился, потому что другая переменная, такая как name , все еще использует его. И это причина, почему строки являются НЕМЕРТНЫМИ .
StringBuilder работает по-другому и не использует пул строк. Когда мы создаем любой экземпляр StringBuilder:
var address = new StringBuilder(500);
Он выделяет кусок памяти размером 500 байт для этого экземпляра, и все операции просто изменяют эту область памяти, и эта память не используется совместно с любым другим объектом. И это причина , почему StringBuilder является Мутабельном .
Надеюсь, это поможет.
Нет, на самом деле. Класс 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 и т. Д., И используете арифметику указателей для копирования в новую строку. Струны просто не изменяются сами по себе, поэтому их считают «неизменяемыми».
Кстати, не пытайтесь делать это с помощью строковых литералов, иначе вы испортите вашу программу:
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, в которой отсутствует интернирование строк.
Для пояснения, в C # (или в целом .NET) нет такой вещи, как изменяемая строка. Другие языки поддерживают изменяемые строки (строки, которые могут изменяться), а платформа .NET - нет.
Таким образом, правильный ответ на ваш вопрос - ВСЕ строки неизменны в C #.
Строка имеет особое значение. Строковое ключевое слово "string" - это просто ярлык для объекта, созданного из класса System.String. Все объекты, созданные из строкового класса, ВСЕГДА неизменны.
Если вам нужно изменяемое представление текста, вам нужно использовать другой класс, например StringBuilder. StringBuilder позволяет итеративно создавать коллекцию «слов», а затем преобразовывать ее в строку (снова неизменяемую).
StringBuilder
противоречит этому: см. Msdn.microsoft.com/en-us/library/…
Значение данных не может быть изменено. Примечание. Значение переменной может быть изменено, но исходное значение неизменяемых данных было отброшено, а новое значение данных было создано в памяти.
От http://yassershaikh.com/what-is-the-difference-between-strings-and-stringbuilder-in-c-net/
Краткий ответ: String является неизменным - тогда как StringBuilder является изменяемым.
Что это значит ? Вики говорит: В объектно-ориентированном виде неизменный объект - это объект, состояние которого нельзя изменить после его создания. Это отличается от изменчивого объекта, который можно изменить после его создания.
Из документации класса StringBuilder:
Объект String является неизменным. Каждый раз, когда вы используете один из методов в классе System.String, вы создаете новый строковый объект в памяти, который требует нового выделения пространства для этого нового объекта.
В ситуациях, когда необходимо выполнить повторные изменения строки, накладные расходы, связанные с созданием нового объекта String, могут быть дорогостоящими.
Класс System.Text.StringBuilder может использоваться, когда вы хотите изменить строку без создания нового объекта. Например, использование класса StringBuilder может повысить производительность при объединении множества строк в цикле.
Вот пример для неизменной строки и строителя изменяемой строки
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();
Строка в C # неизменна. Если вы объединяете его с какой-либо строкой, вы фактически создаете новую строку, то есть новый строковый объект! Но StringBuilder создает изменяемую строку.
StringBuilder - лучший вариант для конкатенации огромной строки данных, поскольку StringBuilder является изменяемым строковым типом, а объект StringBuilder является неизменяемым типом, то есть StringBuilder никогда не создает новый экземпляр объекта во время конкататации строки.
Если мы используем строку вместо StringBuilder для достижения конкатенации, то он будет каждый раз создавать новый экземпляр в памяти.