Skip to Content

Interpolation

Strings beginning with $ support interpolation: the expression in a brace hole is evaluated, converted to text, and spliced into the string. Holes are not limited to variables; arithmetic and function calls work too.

Syntax forms

The full form is {expression,alignment:format}: the first , introduces the alignment width, the first : introduces the format spec, and both parts are optional.

Format verbs

A format spec is a verb plus an optional precision digit (as in F2, N0). The verbs share the table with numeric ToString(format); there are four:

VerbMeaningExampleOutput
Ffixed-point; the digit sets decimal places{pi:F2}3.14
Nthousands grouping; the digit sets decimal places (default 2){1234567:N0} / {1234567:N}1,234,567 / 1,234,567.00
Xhexadecimal (integers only); uppercase {n:X} gives 2A, lowercase {n:x} gives 2a{n:X}2A
Ppercentage (times 100 plus %); the digit sets decimal places{0.25:P0} / {0.5:P1}25 % / 50.0 %
  • Format strings render with InvariantCulture and do not vary with the system locale.
  • Non-numeric types (strings, bool, Duration, and so on) ignore the format part: for a string, {s:F2} just prints it as is.
  • An empty format part is the same as writing none.

Alignment

Alignment is an integer width: positive right-aligns, negative left-aligns; shortfalls are padded with spaces, and overflow is never truncated.

val pi = 3.14159; print($"right-aligned [{pi,10}] left-aligned [{pi,-10}]");
right-aligned [ 3.14159] left-aligned [3.14159 ]

Escapes and edge cases

  • {{ and }} output literal braces: $"{{a}}" gives {a}; the r$ forms follow the same rule.
  • String literals and nested parentheses are allowed inside a hole; they do not close the outer string early.
  • The colon of a ternary ? : is taken as the format separator; wrap complex expressions in parentheses: $"{(cond ? a : b)}".
  • Interpolation strings do not span lines; for multiline use r$#"..."#.
  • A non-integer literal in the alignment slot is treated as 0.

r$: raw plus interpolation

r$"..." and r$#"..."# combine raw with interpolation: no backslash escapes (\n is the literal two characters), the literal segment can span lines, and holes still fire.

val name = "handbook"; print(r$"no escapes \n stay raw, {name} interpolates");
no escapes \n stay raw, handbook interpolates
Last updated on October 11, 2026