How String Interpolation Works in C
String interpolation in C# provides a readable, concise syntax to
format and construct strings by embedding expressions directly inside
string literals. Introduced in C# 6 and enhanced in subsequent versions,
this feature replaces older methods like string.Format and
concatenation. This article explains how string interpolation works
under the hood, how the compiler optimizes it using interpolated string
handlers, and how to use advanced formatting, alignment, and
escaping.
Basic Syntax
To use string interpolation, prepend a string literal with the
$ symbol. Expressions placed inside curly braces
{} are evaluated and converted to their string
representations at runtime:
string name = "Alice";
int age = 30;
string message = $"Hello, {name}! You are {age} years old.";How the Compiler Handles Interpolation
How C# processes interpolated strings depends on the version of the language and the runtime.
Legacy Behavior (C# 6 to C# 9)
In earlier versions, the compiler translated interpolated strings
directly into calls to string.Format:
// Written code:
string result = $"{name} is {age}";
// Compiler output:
string result = string.Format("{0} is {1}", name, (object)age);While convenient, this approach had performance overheads: value
types (like int or struct) were boxed to
object, and an object[] array had to be
allocated to pass the arguments.
Modern Behavior (C# 10 and Newer)
Starting with C# 10 and .NET 6, the compiler uses
interpolated string handlers
(DefaultInterpolatedStringHandler). Instead of delegating
to string.Format, the compiler creates an efficient builder
struct that:
- Allocates the required buffer space in memory upfront.
- Directly appends literals and variables without boxing value types.
- Allows custom handlers to skip string evaluation entirely (for example, skipping expensive formatting when logging at a disabled log level).
Alignment and Formatting Components
Interpolated expressions support optional alignment and format
specifiers using the syntax
{expression,-alignment:format}.
- Alignment: A positive integer right-aligns the text; a negative integer left-aligns it.
- Format Strings: Standard or custom format strings
follow a colon
:.
decimal price = 123.456m;
DateTime today = DateTime.Now;
// Right-aligned to 10 characters and formatted as currency
Console.WriteLine($"Price: {price,10:C2}");
// Formatted date
Console.WriteLine($"Date: {today:yyyy-MM-dd}");Using Ternary and Complex Expressions
Any valid C# expression can be placed inside an interpolated hole. If the expression contains a colon—such as a conditional (ternary) operator—it must be enclosed in parentheses to avoid ambiguity with the format specifier syntax:
bool isActive = true;
string status = $"User is {(isActive ? "Active" : "Inactive")}";Escaping Braces and Special Characters
- Escaping Braces: To include a literal
{or}inside an interpolated string, double the character ({{or}}). - Verbatim Strings: Combine
$with@to create multiline or escaped-path strings ($@"C:\Users\{name}\"). - Raw String Literals (C# 11+): Use multiple
$symbols alongside three or more double quotes ("""). The number of$symbols indicates how many consecutive curly braces are required to trigger interpolation, making JSON generation seamless:
int id = 42;
string json = $$"""
{
"userId": {{id}},
"status": "ok"
}
""";