Строки в C#: введение в работу со строками

Большое количество задач (если не большинство) при разработке программного обеспечения так или иначе связано с обработкой строк будь то простой вывод в консоль определенных значений, сравнение строк или парсинг текста web-страниц. Даже при первом знакомстве с языком программирования, первое, что мы делаем — это используем строки («Hello world» и т.д.). Именно поэтому умение работы со строками в C#, как и в любом другом языке программирования, является одним из необходимых и важных навыков программиста. В этой и нескольких последующих статьях мы рассмотрим основные возможности работы со строками в C#.

Строка в C#

Строки в C# относятся к неизменяемым типам данных и представляют собой объекты класса System.String. Объекты этого класса представляют текст в виде последовательности символов Unicode. При необходимости, никто не мешает нам изменять кодировку символов в строке C# и об этом мы тоже поговорим.

Для тех, кто уже имел дело с другими языками программирования, не лишним будет знать, что в конце строки C# нет нуль-символов. Поэтому в C# мы можем создавать строки, которые содержат любое количество внедренных нуль-символов (\0). При этом, максимальный размер объекта String в памяти составляет 2 Гб.

Создание строк в C#

Объявление и создание строк в C# можно осуществить несколькими способами. Рассмотрим основные из них.

string str1; //объявили переменную типа string
str1 = "Привет";//присвоили строке значение
//объявили и создали строку из двух символов 'a'
string str2 = new String('a', 2);
//объявили и создали строку из массива символов
char[] letters = { 'H', 'e', 'l', 'l', 'o' };
string helloString = new string(letters);
//объявили и создали пустую строку
string emptyStr = string.Empty;

В любом из представленных выше примеров мы создаем строку, при этом, в последнем случае, мы создаем пустую строку без символов. Так как строки относятся к ссылочным типам данных, то никто нам не запрещает присвоить строке значение null

string nullStr = null;

хотя, разработчики C# и предупреждают нас о том, что использование string.Empty вместо null предпочтительнее и  снижает вероятность получения исключения типа NullReferenceException.

Строки с регулярными и буквальными литералами

Отдельное внимание при создании строк также стоит уделить такому моменту, как создание строк, содержащих какие-либо служебные символы. Например, если вам необходимо присвоить строке значение, указывающее на путь к файлу: c:\Program Files\dotnet\dotnet.exe. Если вы попробуете присвоить строке это значение как есть, то ваша программа даже не будет скомпилирована, так как Visual Studio укажет вам на ошибку:

Ошибка CS1009 Нераспознанная escape-последовательность

Все дело в том, что символ обратной косой черты \ используется в строках для указания так называемых escape-последовательностей и для того, чтобы создать строку, содержащую символ  \ нам необходимо либо регулярный строковый литерал, либо буквальный литерал, как показано ниже:

//использование регулярного литерала
string path = "c:\\Program Files\\dotnet\\dotnet.exe";
//использование буквального литерала
string path2 = @"c:\Program Files\dotnet\dotnet.exe";

Использование регулярного литерала позволяет нам использовать различные escape-последовательности в строках. В таблице ниже представлены основные escape-последовательности в C#:

Escape-последовательность Имя символа Кодировка Юникод
\’ Одинарная кавычка 0x0027
Двойная кавычка 0x0022
\\ Обратная косая черта 0x005C
\0 Null 0x0000
\a Предупреждение 0x0007
\b Backspace 0x0008
\f Перевод страницы 0x000C
\n Новая строка 0x000A
\r Возврат каретки 0x000D
\t Горизонтальная табуляция 0x0009
\v Вертикальная табуляция 0x000B
\u Escape-последовательность Юникода (UTF-16) \uHHHH (диапазон: 0000–FFFF; пример: \u00E7 = «ç»)
\U Escape-последовательность Юникода (UTF-32) \U00HHHHHH (диапазон: 000000–10FFFF; пример: \U0001F47D = «👽»)
\x Escape-последовательность Юникода аналогична «\u», она отличается только длиной переменной \xH[H][H][H] (диапазон: 0–FFFF; пример: \x00E7 или \x0E7 или \xE7 = «ç»)

Например, используя escape-последовательности, мы можем вывести в консоль таблицу:

//выводим в консоль таблицу 3х3
Console.WriteLine("Номер\tЗначение\tОписание");
Console.WriteLine("1\t0,1\t\tописание 1");
Console.WriteLine("2\t0,2\t\tописание 2");
Console.WriteLine("3\t0,3\t\tописание 3");

В итоге, в консоли мы увидим вот такую красивую табличку:

Что касается использования буквального литерала в строках, то его удобно использовать для того, чтобы сделать строки, содержащие какие-либо служебные символы, более читабельными. Согласитесь, что такая строка:

string path2 = @"c:\Program Files\dotnet\dotnet.exe";

выглядит более читабельной, чем вот такая:

string path = "c:\\Program Files\\dotnet\\dotnet.exe";

Более того, так как буквальный литерал позволяет сохранять все символы в строке как есть, то, используя его, мы можем использовать в наших строках переносы, кавычки и прочие символы как есть, например:

//использование буквального литерала
            string str = @"Эта строка содержит символ \ , а также одинарные кавычки 'текст в кавычках' 
                           и переносы строки
                           ";

В результате, в консоли мы увидим следующий текст:

Неизменяемость строк в C#

Как уже упоминалось выше, строки в C# относятся к неизменяемым типам данных. Что это значит для нас? А это значит, что при каждом присвоении значения переменной типа string система вначале освобождает память, занятую строкой, а затем выделяет по новой и только потом записывает новое значение. С одной стороны, подобный подход выглядит нерациональным — лишние освобождения и выделения памяти, но, с другой стороны, таким образом разработчики C# обеспечили максимальную безопасность работы со строками и, надо сказать, сделали это достаточно элегантно и понятно. Например,

string str4; //объявили переменную
str4 = "hello"; //выделили память под 5 символов и присвоили значение переменной
str4 = "hello world";//освободили память, по новой выделили память уже под 11 символов и присвоили новое значение

Также стоит отметить, что когда содержимое двух строк, например, s1 и s2 объединяется для формирования строки, то две исходные строки не изменяются. Например:

string s1 = "Hello ";
string s2 = "world";

s1 += s2;
Console.WriteLine(s1);

В примере выше оператор += создает новую строку, которая содержит объединенное содержимое двух строк. Этот новый объект присваивается переменной s1, а исходный объект, который был присвоен s1, освобождается для сборки мусора, так как ни одна переменная не ссылается на него.

Если вы создадите ссылку на строку, а затем «измените» исходную строку, ссылка будет по-прежнему указывать на исходный объект, а не на новый, который был создан при изменении строки. Пример:

string s1 = "Hello ";
string s2 = s1;
s1 += "World";
Console.WriteLine(s2);

В представленном примере может показаться, что в итоге, в консоли будет строка "Hello world", однако, на самом деле в консоли мы увидим только "Hello "так как строка s2 остается неизменной.

Итого

Сегодня мы узнали как создавать строки в C#, как использовать различные escape-последовательности в строках, а также использовать буквальный литерал для повышения читабельности строк в C#. Также рассмотрели некоторые моменты, касающиеся неизменности строк в C# и как эта неизменность проявляется.

Подписаться
Уведомить о
guest
0 Комментарий
Старые
Новые Популярные
Межтекстовые Отзывы
Посмотреть все комментарии