Яка різниця між змінним і незмінним рядком в 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. Thestring
Ключовим словом є псевдонімом для цього класу.
The System.String незмінний, тобто щойно створений стан не може бути змінений .
Отже всі операції, які ви виконуєте в рядку Substring
,Remove
,Replace
, конкатенації з допомогою оператора «+» і т.д. створить новий рядок і повернути його.
Дивіться наступну програму для демонстрації -
string str = "mystring";
string newString = str.Substring(2);
Console.WriteLine(newString);
Console.WriteLine(str);
Це надрукує "string" та "mystring" відповідно.
Для переваг непорушності та чому рядки є незмінними перевірити Чому .NET String є незмінним?.
Якщо ви хочете мати рядок, яку ви хочете часто змінювати, ви можете використовувати 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";
Він буде шукати пул рядків для рядка "My Loving Country", якщо його знайдете, ви отримаєте посилання на нього, інший мудрий новий рядок "My Loving Country" буде створений у ряді string та name2 отримає посилання на нього. Але це весь цей процес " Моя країна " не було змінено, оскільки інша змінна, як ім'я , все ще використовує її. І це є причиною того, що рядок НЕПРАВНИЙ .
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 Framework цього не робить.
Тож правильна відповідь на ваше запитання - ВСІ рядки незмінні в C #.
рядок має конкретне значення. Ключове слово рядка "рядка" - це лише ярлик для об'єкта, створеного з класу System.String. Усі об'єкти, створені з рядкового класу, ЗАВЖДИ незмінні.
Якщо ви хочете змінювати подання тексту, вам потрібно використовувати інший клас, наприклад StringBuilder. StringBuilder дозволяє ітеративно скласти колекцію "слів", а потім перетворити їх у рядок (знову незмінний).
StringBuilder
суперечить цьому: див. Msdn.microsoft.com/en-us/library/…
Значення даних може бути змінено. Примітка. Значення змінної може бути змінено, але вихідне значення незмінного даних було відкинуто і в пам'яті створено нове значення даних.
З http://yassershaikh.com/what-is-the-difference-bet between-strings-and-stringbuilder-in-c-net/
Короткий відповідь: Рядок незмінний - тоді як StringBuilder є змінним.
Що це означає ? Wiki каже: У об'єктно-орієнтованому незмінному об'єкті є об'єкт, стан якого не може бути змінений після його створення. Це на відміну від об'єкта, що змінюється, який можна змінити після його створення.
З документації до класу 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 для досягнення конкатенації, то вона буде створювати новий екземпляр у пам'яті кожного разу.