$ — интерполяция строк (справочные материалы по C#)

Специальный знак $ идентифицирует строковый литерал как интерполированную строку. Интерполированная строка — это строковый литерал, который может содержать выражения интерполяции. При разрешении интерполированной строки в результирующую элементы с выражениями интерполяции заменяются строковыми представлениями результатов выражений.

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

string name = "Mark";
var date = DateTime.Now;

// Composite formatting:
Console.WriteLine("Hello, {0}! Today is {1}, it's {2:HH:mm} now.", name, date.DayOfWeek, date);
// String interpolation:
Console.WriteLine($"Hello, {name}! Today is {date.DayOfWeek}, it's {date:HH:mm} now.");
// Both calls produce the same output that is similar to:
// Hello, Mark! Today is Wednesday, it's 19:40 now.

Структура интерполированной строки

Для определения строкового литерала в качестве интерполированной строки добавьте к началу символ $. Между $ и " в начале строкового литерала не может быть пробела. Чтобы сцепить несколько интерполированных строк, добавьте специальный $ символ в каждый строковый литерал.

Структура элемента с выражением интерполяции выглядит следующим образом:

{<interpolationExpression>[,<alignment>][:<formatString>]}

Элементы в квадратных скобках являются необязательными. Каждый из элементов описан в таблице ниже:

Элемент Описание
interpolationExpression Выражение, создающее форматируемый результат. Строковое представление null является String.Empty.
alignment Константное выражение, значение которого определяет минимальное количество символов в строковом представлении результата выражения. Если оно положительное, строковое представление выравнивается по правому краю, если отрицательное — по левому краю. Дополнительные сведения см. в разделе Компонент выравнивания.
formatString Строка форматирования, поддерживаемая типом результата выражения. Дополнительные сведения см. в разделе Компонент строки форматирования.

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

Console.WriteLine($"|{"Left",-7}|{"Right",7}|");

const int FieldWidthRightAligned = 20;
Console.WriteLine($"{Math.PI,FieldWidthRightAligned} - default formatting of the pi number");
Console.WriteLine($"{Math.PI,FieldWidthRightAligned:F3} - display only three decimal digits of the pi number");
// Expected output is:
// |Left   |  Right|
//     3.14159265358979 - default formatting of the pi number
//                3.142 - display only three decimal digits of the pi number

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

Начиная с C# 11, в интерполированных выражениях могут содержаться символы новой строки. Текст между { и } должен быть допустимым кодом C#, поэтому он может содержать символы новой строки, которые улучшают удобочитаемость. В следующем примере показано, как новая строка может повысить удобочитаемость выражения, включающего сопоставление шаблонов:

string message = $"The usage policy for {safetyScore} is {
    safetyScore switch
    {
        > 90 => "Unlimited usage",
        > 80 => "General usage, with daily safety check",
        > 70 => "Issues must be addressed within 1 week",
        > 50 => "Issues must be addressed within 1 day",
        _ => "Issues must be addressed before continued use",
    }
    }";

Кроме того, начиная с версии C# 11, вы можете использовать необработанный строковый литерал для строки формата:

int X = 2;
int Y = 3;

var pointMessage = $"""The point "{X}, {Y}" is {Math.Sqrt(X * X + Y * Y)} from the origin""";

Console.WriteLine(pointMessage);
// output:  The point "2, 3" is 3.605551275463989 from the origin.

В интерполированном необработанном строковом литерале можно использовать несколько символов $ для включения в строку вывода символов { и } без экранирования:

int X = 2;
int Y = 3;

var pointMessage = $$"""The point {{{X}}, {{Y}}} is {{Math.Sqrt(X * X + Y * Y)}} from the origin""";
Console.WriteLine(pointMessage);
// output:  The point {2, 3} is 3.605551275463989 from the origin.

Если строка вывода должна содержать повторяющиеся символы { или }, вы можете добавить дополнительные $, чтобы обозначить интерполированную строку. Любая последовательность { или } короче числа $ будет внедрена в выходную строку. Как показано в предыдущем примере, последовательности большей длины, чем у последовательности $, внедряют дополнительные символы { или } в выходные данные. Если последовательность фигурных скобок как минимум вдвое превышает длину последовательности символов $, компилятор выдает ошибку.

Вы можете опробовать эти функции с помощью пакета SDK для .NET 7. Если же вы используете пакет SDK для .NET версии 6.00.200 или выше, можете задать элементу <LangVersion> в файле csproj значение preview.

Специальные символы

Чтобы включить в текст, создаваемый интерполированной строкой, фигурную скобку "{" или "}", используйте две фигурные скобки — "{{" или "}}". Подробнее см. в разделе Экранирование фигурных скобок.

Так как двоеточие (:) имеет особое значение в элементе выражения интерполяции, чтобы использовать условный оператор в выражении интерполяции, заключите это выражение в круглые скобки.

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

string name = "Horace";
int age = 34;
Console.WriteLine($"He asked, \"Is your name {name}?\", but didn't wait for a reply :-{{");
Console.WriteLine($"{name} is {age} year{(age == 1 ? "" : "s")} old.");
// Expected output is:
// He asked, "Is your name Horace?", but didn't wait for a reply :-{
// Horace is 34 years old.

Интерполированная строка verbatim начинается с символа $, за которым следует символ @. Маркеры и @ можно использовать $ в любом порядке: и $@"..."@$"..." являются допустимыми интерполированными дословно строками. Дополнительные сведения о буквальных строках см. в статьях о строках и буквальном идентификаторе.

Неявные преобразования и указание реализации IFormatProvider

Существует три неявных преобразования из интерполированных строк.

  1. Преобразование интерполированной строки в экземпляр String. Строка является результатом разрешения интерполированной строки. Все элементы выражений интерполяции заменяются правильно форматированными представлениями строк их результатов. Это преобразование использует CurrentCulture для форматирования результатов выражений.

  2. Преобразование интерполированной строки в экземпляр FormattableString, представляющий строку составного формата, а также форматируемые результаты выражения. Это позволяет создавать несколько результирующих строк с содержимым для конкретного языка из одного экземпляра FormattableString. Для этого вызовите один из следующих методов:

    • Перегрузка ToString(), которая формирует результирующую строку для CurrentCulture.
    • Метод Invariant, который формирует результирующую строку для InvariantCulture.
    • Метод ToString(IFormatProvider), который формирует результирующую строку для указанного языка и региональных параметров.

    Метод ToString(IFormatProvider) предоставляет пользовательские реализации интерфейса IFormatProvider, который поддерживает настраиваемое форматирование. Дополнительные сведения см. в статье Типы форматирования в .NET, разделе Настраиваемое форматирование с использованием интерфейса ICustomFormatter.

  3. Преобразование интерполированной строки в экземпляр IFormattable, который также позволяет создавать несколько результирующих строк с содержимым для конкретного языка из одного экземпляра IFormattable.

В следующем примере используется неявное преобразование в FormattableString для создания результирующих строк для конкретного языка:

double speedOfLight = 299792.458;
FormattableString message = $"The speed of light is {speedOfLight:N3} km/s.";

System.Globalization.CultureInfo.CurrentCulture = System.Globalization.CultureInfo.GetCultureInfo("nl-NL");
string messageInCurrentCulture = message.ToString();

var specificCulture = System.Globalization.CultureInfo.GetCultureInfo("en-IN");
string messageInSpecificCulture = message.ToString(specificCulture);

string messageInInvariantCulture = FormattableString.Invariant(message);

Console.WriteLine($"{System.Globalization.CultureInfo.CurrentCulture,-10} {messageInCurrentCulture}");
Console.WriteLine($"{specificCulture,-10} {messageInSpecificCulture}");
Console.WriteLine($"{"Invariant",-10} {messageInInvariantCulture}");
// Expected output is:
// nl-NL      The speed of light is 299.792,458 km/s.
// en-IN      The speed of light is 2,99,792.458 km/s.
// Invariant  The speed of light is 299,792.458 km/s.

Другие ресурсы

Если у вас нет опыта работы с интерполяцией строк, ознакомьтесь с интерактивным учебником по интерполяции строк в C#. Вы можете также просмотреть другой учебник по интерполяции строк в C#. В этом учебнике показано, как использовать интерполированные строки для создания форматированных строк.

Компиляция интерполированных строк

Если интерполированная строка имеет тип string, обычно она преобразуется в вызов метода String.Format. Компилятор может заменить String.Format на String.Concat, если проанализированное поведение будет эквивалентно объединению.

Если интерполированная строка имеет тип IFormattable или FormattableString, компилятор создает вызов метода FormattableStringFactory.Create.

Начиная с C# 10 при использовании интерполированной строки компилятор проверяет, назначена ли эта строка типу, отвечающему требованиям шаблона обработчика интерполированных строк. Обработчик интерполированных строк — это настраиваемый тип, который преобразует интерполированную строку в строку. Обработчик интерполированных строк — это расширенный сценарий, который обычно используется для повышения производительности. Вы можете узнать о требованиях для создания обработчика интерполированных строк в спецификации языка для улучшения интерполированных строк. Вы можете создать одну из них, выполнив инструкции из учебника по обработчику интерполированных строк в разделе C# "Новые возможности". В .NET 6 при использовании интерполированной строки для аргумента типа string эта строка обрабатывается с помощью System.Runtime.CompilerServices.DefaultInterpolatedStringHandler.

Примечание

Одним из побочных эффектов обработчиков интерполированных строк является то, что пользовательский обработчик, включая System.Runtime.CompilerServices.DefaultInterpolatedStringHandler, может не оценивать все выражения, используемые в качестве заполнителей в интерполированной строке при всех условиях. Это означает, что побочные эффекты в этих выражениях могут не возникнуть.

Спецификация языка C#

Дополнительные сведения см. в разделе Интерполированные строки спецификацииязыка C#, спецификации функции необработанных строковых литералов C# 11 и спецификации функций C# 11 — Новые строки в интерполяции строк .

См. также