String interpolation using $

The $ special character identifies a string literal as an interpolated string. An interpolated string is a string literal that might contain interpolation expressions. When an interpolated string is resolved to a result string, items with interpolation expressions are replaced by the string representations of the expression results.

String interpolation provides a more readable, convenient syntax to format strings. It's easier to read than string composite formatting. Compare the following example that uses both features to produce the same output:

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.

Structure of an interpolated string

To identify a string literal as an interpolated string, prepend it with the $ symbol. You can't have any white space between the $ and the " that starts a string literal. To concatenate multiple interpolated strings, add the $ special character to each string literal.

The structure of an item with an interpolation expression is as follows:


Elements in square brackets are optional. The following table describes each element:

Element Description
interpolationExpression The expression that produces a result to be formatted. String representation of null is String.Empty.
alignment The constant expression whose value defines the minimum number of characters in the string representation of the expression result. If positive, the string representation is right-aligned; if negative, it's left-aligned. For more information, see Alignment Component.
formatString A format string that is supported by the type of the expression result. For more information, see Format String Component.

The following example uses optional formatting components described above:


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

Beginning with C# 10, you can use string interpolation to initialize a constant string. All expressions used for placeholders must be constant strings. In other words, every interpolation expression must be a string, and it must be a compile time constant.

Beginning with C# 11, the interpolated expressions can include newlines. The text between the { and } must be valid C#, therefore it can include newlines that improve readability. The following example shows how newlines can improve the readability of an expression involving pattern matching:

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",

Also, beginning in C# 11, you can use a raw string literal for the format string:

int X = 2;
int Y = 3;

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

// output:  The point "2, 3" is 3.605551275463989 from the origin.

You can use multiple $ characters in an interpolated raw string literal to embed { and } characters in the output string without escaping them:

int X = 2;
int Y = 3;

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

If your output string should contain repeated { or } characters, you can add more $ to designate the interpolated string. Any sequence of { or } shorter than the number of $ will be embedded in the output string. As shown in the preceding example, sequences longer than the sequence of $ characters embed the additional { or } characters in the output. The compiler issues an error if the sequence of brace characters is equal to or greater than double the length of the sequence of $ characters.

You can try these features using the .NET 7 SDK. Or, if you have the .NET SDK 6.00.200 or later, you can set the <LangVersion> element in your csproj file to preview.

Special characters

To include a brace, "{" or "}", in the text produced by an interpolated string, use two braces, "{{" or "}}". For more information, see Escaping Braces.

As the colon (":") has special meaning in an interpolation expression item, to use a conditional operator in an interpolation expression, enclose that expression in parentheses.

The following example shows how to include a brace in a result string. It also shows how to use a conditional operator:

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.

An interpolated verbatim string starts with the $ character followed by the @ character. You can use the $ and @ tokens in any order: both $@"..." and @$"..." are valid interpolated verbatim strings. For more information about verbatim strings, see the string and verbatim identifier articles.

Implicit conversions and how to specify IFormatProvider implementation

There are three implicit conversions from an interpolated string:

  1. Conversion of an interpolated string to a String instance. The string is the result of interpolated string resolution. All interpolation expression items are replaced with the properly formatted string representations of their results. This conversion uses the CurrentCulture to format expression results.

  2. Conversion of an interpolated string to a FormattableString instance that represents a composite format string along with the expression results to be formatted. That allows you to create multiple result strings with culture-specific content from a single FormattableString instance. To do that, call one of the following methods:

    The ToString(IFormatProvider) provides a user-defined implementation of the IFormatProvider interface that supports custom formatting. For more information, see the Custom formatting with ICustomFormatter section of the Formatting types in .NET article.

  3. Conversion of an interpolated string to an IFormattable instance that also allows you to create multiple result strings with culture-specific content from a single IFormattable instance.

The following example uses implicit conversion to FormattableString to create culture-specific result strings:

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.

Other resources

If you're new to string interpolation, see the String interpolation in C# interactive tutorial. You can also check another String interpolation in C# tutorial. That tutorial demonstrates how to use interpolated strings to produce formatted strings.

Compilation of interpolated strings

If an interpolated string has the type string, it's typically transformed into a String.Format method call. The compiler may replace String.Format with String.Concat if the analyzed behavior would be equivalent to concatenation.

If an interpolated string has the type IFormattable or FormattableString, the compiler generates a call to the FormattableStringFactory.Create method.

Beginning with C# 10, when an interpolated string is used, the compiler checks if the interpolated string is assigned to a type that satisfies the interpolated string handler pattern. An interpolated string handler is a custom type that converts the interpolated string into a string. An interpolated string handler is an advanced scenario, typically used for performance reasons. You can learn about the requirements to build an interpolated string handler in the language specification for interpolated string improvements. You can build one following the interpolated string handler tutorial in the What's new in C# section. In .NET 6, when you use an interpolated string for an argument of type string, the interpolated string is processed by the System.Runtime.CompilerServices.DefaultInterpolatedStringHandler.


One side effect of interpolated string handlers is that a custom handler, including System.Runtime.CompilerServices.DefaultInterpolatedStringHandler, may not evaluate all the expressions used as placeholders in the interpolated string under all conditions. That means side-effects in those expressions may not occur.

C# language specification

For more information, see the Interpolated strings section of the C# language specification, the C# 11 - Raw string literals feature specification and the C# 11 - Newlines in string interpolations feature specification.

See also