• Статья
  • Чтение занимает 5 мин

Строка — это объект типа String, значением которого является текст. Внутри программы текст хранится в виде упорядоченной коллекции объектов Char только для чтения. В конце строки C# нет нуль-символов. Поэтому строка C# может содержать любое число внедренных нуль-символов (‘’). Свойство Length строки соответствует числу содержащихся в ней объектов Char, но не числу символов Юникода. Для доступа к отдельным кодовым точкам Юникода в строке используйте объект StringInfo.

Сравнение строки и System.String

В C# ключевое слово string является псевдонимом для String. Таким образом, String и string являются эквивалентами. Однако рекомендуется использовать предоставленный псевдоним string, так как он работает даже без using System;. Класс String предоставляет множество методов для безопасного создания, обработки и сравнения строк. Кроме того, язык C# перегружает некоторые операторы для упрощения типичных операций со строками. Дополнительные сведения о ключевых словах см. в статье, посвященной строкам. Дополнительные сведения о типе и его методах см. здесь: String.

Объявление и инициализация строк

Вы можете объявлять и инициализировать строки различными способами, как показано в следующем примере:

// Declare without initializing.
string message1;

// Initialize to null.
string message2 = null;

// Initialize as an empty string.
// Use the Empty constant instead of the literal "".
string message3 = System.String.Empty;

// Initialize with a regular string literal.
string oldPath = "c:Program FilesMicrosoft Visual Studio 8.0";

// Initialize with a verbatim string literal.
string newPath = @"c:Program FilesMicrosoft Visual Studio 9.0";

// Use System.String if you prefer.
System.String greeting = "Hello World!";

// In local variables (i.e. within a method body)
// you can use implicit typing.
var temp = "I'm still a strongly-typed System.String!";

// Use a const string to prevent 'message4' from
// being used to store another string value.
const string message4 = "You can't get rid of me!";

// Use the String constructor only when creating
// a string from a char*, char[], or sbyte*. See
// System.String documentation for details.
char[] letters = { 'A', 'B', 'C' };
string alphabet = new string(letters);

Обратите внимание, что вы не используете оператор new для создания объекта строки, за исключением случаев инициализации строки с помощью массива символов.

Инициализируйте строку с константным значением Empty для создания нового объекта String, строка которого имеет нулевую длину. Представлением строкового литерала строки с нулевой длиной является «». Если вы инициализируете строки со значением Empty вместо NULL, вы снизите вероятность появления исключения NullReferenceException. Используйте статический метод IsNullOrEmpty(String), чтобы проверить значение строки, прежде чем пытаться получить к ней доступ.

Неизменность строковых объектов

Строковые объекты являются неизменяемыми: их нельзя изменить после создания. Может показаться, что все методы String и операторы C# изменяют строку, но в действительности они возвращают результаты в новый строковый объект. Когда содержимое s1 и s2 объединяется для формирования одной строки, две исходные строки не изменяются, как показано в следующем примере. Оператор += создает новую строку, которая содержит объединенное содержимое. Этот новый объект присваивается переменной s1, а исходный объект, который был присвоен s1, освобождается для сборки мусора, так как ни одна переменная не ссылается на него.

string s1 = "A string is more ";
string s2 = "than the sum of its chars.";

// Concatenate s1 and s2. This actually creates a new
// string object and stores it in s1, releasing the
// reference to the original object.
s1 += s2;

System.Console.WriteLine(s1);
// Output: A string is more than the sum of its chars.

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

string s1 = "Hello ";
string s2 = s1;
s1 += "World";

System.Console.WriteLine(s2);
//Output: Hello

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

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

Используйте регулярные строковые литералы, когда вам нужно внедрить escape-символы, доступные в C#, как показано в следующем примере:

string columns = "Column 1tColumn 2tColumn 3";
//Output: Column 1        Column 2        Column 3

string rows = "Row 1rnRow 2rnRow 3";
/* Output:
  Row 1
  Row 2
  Row 3
*/

string title = ""The u00C6olean Harp", by Samuel Taylor Coleridge";
//Output: "The Æolean Harp", by Samuel Taylor Coleridge

Буквальные строковые литералы используются для удобства и читабельности, если текст строки содержит символы обратной косой черты, например в путях к файлам. Так как буквальные строки сохраняют символы новой строки как часть текста строки, их можно использовать для инициализации многострочных строк. Используйте двойные кавычки, чтобы вставить кавычки в буквальной строке. В следующем примере показаны наиболее часто используемым буквальные строки:

string filePath = @"C:UsersscoleridgeDocuments";
//Output: C:UsersscoleridgeDocuments

string text = @"My pensive SARA ! thy soft cheek reclined
    Thus on mine arm, most soothing sweet it is
    To sit beside our Cot,...";
/* Output:
My pensive SARA ! thy soft cheek reclined
   Thus on mine arm, most soothing sweet it is
   To sit beside our Cot,...
*/

string quote = @"Her name was ""Sara.""";
//Output: Her name was "Sara."

Escape-последовательности строк

Escape-последовательность Имя символа Кодировка Юникод
Одинарная кавычка 0x0027
« Двойная кавычка 0x0022
Обратная косая черта 0x005C
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-последовательность x с менее чем четырьмя шестнадцатеричными цифрами, то когда непосредственно следующие за ней символы также являются допустимыми шестнадцатеричными цифрами (т. е. 0–9, A–F и a–f), они будут интерпретированы как часть этой escape-последовательности. Например, xA1 дает результат «¡», являющийся кодовой точкой U+00A1. Однако если следующий символ — «A» или «a», тогда escape-последовательность будет интерпретироваться как xA1A и даст результат «ਚ», являющийся кодовой точкой U+0A1A. В таких случаях, чтобы избежать некорректной интерпретации, указывайте все четыре шестнадцатеричных знака (например, x00A1).

Примечание

Во время компиляции буквальные строки преобразуются в обычные строки с теми же escape-последовательностями. Поэтому, если вы просматриваете буквальную строку в окне контрольных значений отладчика, вы увидите escape-символы, добавленные компилятором, а не буквальную версию из исходного кода. Например, буквальная строка @"C:files.txt"будет отображаться в окне контрольных значений как «C:files.txt».

Строки формата

Строка формата — это строка, содержимое которой можно определить динамически во время выполнения. Строки формата создаются путем внедрения интерполированных выражений или заполнителей внутри фигурных скобок в строке. Весь код внутри фигурных скобок ({...}) будет преобразован в значение и выходные данные как отформатированная строка во время выполнения. Существует два способа создания строк формата: интерполяция строк и составное форматирование.

Интерполяция строк

В C# 6.0 и более поздних версий интерполированные строки определяются по специальному символу $. Они включают интерполированные выражения в фигурных скобках. См. дополнительные сведения в интерактивном руководстве по интерполяции строк в C#.

Используйте интерполяцию для повышения удобства чтения и обслуживаемости кода. Интерполяция строк позволяет достичь тех же результатов, что и использование метода String.Format, но более простым и понятным способом.

var jh = (firstName: "Jupiter", lastName: "Hammon", born: 1711, published: 1761);
Console.WriteLine($"{jh.firstName} {jh.lastName} was an African American poet born in {jh.born}.");
Console.WriteLine($"He was first published in {jh.published} at the age of {jh.published - jh.born}.");
Console.WriteLine($"He'd be over {Math.Round((2018d - jh.born) / 100d) * 100d} years old today.");

// Output:
// Jupiter Hammon was an African American poet born in 1711.
// He was first published in 1761 at the age of 50.
// He'd be over 300 years old today.

Начиная с C# 10, можно использовать интерполяцию строк для инициализации константной строки, если все выражения, используемые для заполнителей, также являются константными строками.

Составное форматирование

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

var pw = (firstName: "Phillis", lastName: "Wheatley", born: 1753, published: 1773);
Console.WriteLine("{0} {1} was an African American poet born in {2}.", pw.firstName, pw.lastName, pw.born);
Console.WriteLine("She was first published in {0} at the age of {1}.", pw.published, pw.published - pw.born);
Console.WriteLine("She'd be over {0} years old today.", Math.Round((2018d - pw.born) / 100d) * 100d);

// Output:
// Phillis Wheatley was an African American poet born in 1753.
// She was first published in 1773 at the age of 20.
// She'd be over 300 years old today.

См. дополнительные сведения о типах форматирования в .NET.

Подстроки

Подстрока — это последовательность символов, содержащихся в строке. Используйте метод Substring, чтобы создать новую строку из части исходной строки. Одно вхождение подстроки или несколько можно найти с помощью метода IndexOf. Используйте метод Replace, чтобы заменить все вхождения указанной подстроки новой строкой. Как и метод Substring, метод Replace фактически возвращает новую строку и не изменяет исходную строку. См. дополнительные сведения о поиске строк и изменении содержимого строк.

string s3 = "Visual C# Express";
System.Console.WriteLine(s3.Substring(7, 2));
// Output: "C#"

System.Console.WriteLine(s3.Replace("C#", "Basic"));
// Output: "Visual Basic Express"

// Index values are zero-based
int index = s3.IndexOf("C");
// index = 7

Доступ к отдельным символам

Используя нотацию массива со значением индекса, можно получить доступ только для чтения к отдельным символам, как показано в следующем примере:

string s5 = "Printing backwards";

for (int i = 0; i < s5.Length; i++)
{
    System.Console.Write(s5[s5.Length - i - 1]);
}
// Output: "sdrawkcab gnitnirP"

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

string question = "hOW DOES mICROSOFT wORD DEAL WITH THE cAPS lOCK KEY?";
System.Text.StringBuilder sb = new System.Text.StringBuilder(question);

for (int j = 0; j < sb.Length; j++)
{
    if (System.Char.IsLower(sb[j]) == true)
        sb[j] = System.Char.ToUpper(sb[j]);
    else if (System.Char.IsUpper(sb[j]) == true)
        sb[j] = System.Char.ToLower(sb[j]);
}
// Store the new string.
string corrected = sb.ToString();
System.Console.WriteLine(corrected);
// Output: How does Microsoft Word deal with the Caps Lock key?

Строки NULL и пустые строки

Пустая строка — это экземпляр объекта System.String, который содержит нуль символов. Пустые строки часто используются в различных сценариях программирования для представления пустого текстового поля. Вы можете вызывать методы для пустых строк, так как они являются допустимыми объектами System.String. Пустые строки инициализируются следующим образом:

string s = String.Empty;  

В отличие от пустых строк строка NULL не ссылается на экземпляр объекта System.String, поэтому любая попытка вызвать метод для строки NULL приводит к исключению NullReferenceException. Но вы можете использовать строки NULL в операциях объединения и сравнения с другими строками. В следующих примерах показаны случаи, в которых ссылка на строку NULL вызывает и не вызывает исключение:

static void Main()
{
    string str = "hello";
    string nullStr = null;
    string emptyStr = String.Empty;

    string tempStr = str + nullStr;
    // Output of the following line: hello
    Console.WriteLine(tempStr);

    bool b = (emptyStr == nullStr);
    // Output of the following line: False
    Console.WriteLine(b);

    // The following line creates a new empty string.
    string newStr = emptyStr + nullStr;

    // Null strings and empty strings behave differently. The following
    // two lines display 0.
    Console.WriteLine(emptyStr.Length);
    Console.WriteLine(newStr.Length);
    // The following line raises a NullReferenceException.
    //Console.WriteLine(nullStr.Length);

    // The null character can be displayed and counted, like other chars.
    string s1 = "x0" + "abc";
    string s2 = "abc" + "x0";
    // Output of the following line: * abc*
    Console.WriteLine("*" + s1 + "*");
    // Output of the following line: *abc *
    Console.WriteLine("*" + s2 + "*");
    // Output of the following line: 4
    Console.WriteLine(s2.Length);
}

Использование класса StringBuilder для быстрого создания строк

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

System.Text.StringBuilder sb = new System.Text.StringBuilder("Rat: the ideal pet");
sb[0] = 'C';
System.Console.WriteLine(sb.ToString());
System.Console.ReadLine();

//Outputs Cat: the ideal pet

В этом примере объект StringBuilder используется для создания строки из набора числовых типов:

using System;
using System.Text;

namespace CSRefStrings
{
    class TestStringBuilder
    {
        static void Main()
        {
            var sb = new StringBuilder();

            // Create a string composed of numbers 0 - 9
            for (int i = 0; i < 10; i++)
            {
                sb.Append(i.ToString());
            }
            Console.WriteLine(sb);  // displays 0123456789

            // Copy one character of the string (not possible with a System.String)
            sb[0] = sb[9];

            Console.WriteLine(sb);  // displays 9123456789
            Console.WriteLine();
        }
    }
}

Строки, методы расширения и LINQ

Так как тип String использует IEnumerable<T>, вы можете применять методы расширения, определенные для строк в классе Enumerable. Чтобы избежать визуального загромождения, эти методы исключены из IntelliSense для типа String, но все равно доступны. Можно также использовать выражения запроса LINQ в строках. Дополнительные сведения см. в документации по LINQ и строкам.

Раздел Описание
Практическое руководство. Изменение содержимого строки Описание методов преобразования строк и изменения их содержимого.
Сравнение строк Рассказывает, как строки сравниваются по языку, региональным параметрам и порядку.
Сцепка нескольких строк Демонстрирует разные способы соединения нескольких строк в одну.
Анализ строк с помощью метода String.Split Содержит примеры кода, демонстрирующие использование метода String.Split для анализа строк.
Практическое руководство. Поиск по строкам Описание использования поиска для нахождения в строках определенных шаблонов или текста.
Определение представления числового значения в строке Объясняет, как безопасно проанализировать строку, чтобы проверить, содержит ли она допустимое числовое значение.
Интерполяция строк Описывает функцию интерполяции строк, которая предоставляет удобный синтаксис для форматирования строк.
Базовые операции со строками в .NET Framework Содержит ссылки на статьи, в которых показаны базовые операции над строками с помощью методов System.String и System.Text.StringBuilder.
Анализ строк в .NET Описывает, как преобразовать строковые представления базовых типов .NET в экземпляры соответствующих типов.
Синтаксический анализ строк даты и времени в .NET Показывает, как преобразовать строку, например «01/24/2008», в объект System.DateTime.
Сравнение строк в .NET Framework Объясняет, как сравнивать строки, и содержит примеры на языках C# и Visual Basic.
Using the StringBuilder class (Использование класса StringBuilder) Описывает создание и изменение динамических строковых объектов с помощью класса StringBuilder.
LINQ и строки Содержит инструкции по выполнению различных операций со строками с помощью запросов LINQ.
Руководство по программированию на C# Содержит ссылки на статьи с конструкциями программирования на C#.