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:

  1. Allocates the required buffer space in memory upfront.
  2. Directly appends literals and variables without boxing value types.
  3. 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"
}
""";