C# String Interpolation is a powerful feature that simplifies the syntax for embedding variables and expressions within strings to construct strings dynamically. String interpolation evolved significantly during the last few years. In this post, we’ll explore how to use string interpolation effectively with concise explanations and code samples.
What is String Interpolation?
Introduced in C# 6.0, string interpolation provides a more readable and convenient syntax to create formatted strings compared to traditional methods like String.Format
.
String interpolation in C# is denoted by a dollar sign $
followed by a string literal in curly braces {item}
. For example:
1 2 3 4 |
var name = "John"; var age = 30; var message = $"Hello, my name is {name} and I am {age} years old."; Console.WriteLine(message); |
Hello, my name is John and I am 30 years old.
Notice that Visual Studio, VSCode, and JetBrains Rider highlight interpolation expressions in the editor:
Including Expressions
String interpolation isn’t limited to variables; you can also embed expressions:
1 2 3 4 |
var price = 29.99; var taxRate = 0.08; var total = $"Total cost: {price * (1 + taxRate)}"; Console.WriteLine(total); |
This program outputs: Total cost: 32.3892
Conditional Expressions
You can include conditional expressions within the interpolated strings.
1 2 3 |
var userScore = 1200; var scoreMessage = $"Your score is {userScore} and you are {(userScore > 1000 ? "above" : "below")} average."; Console.WriteLine(scoreMessage); |
Formatting
Interpolation allows for formatting numbers, dates, and more directly with the separator character :
.
For example, the program below outputs Pi to three decimal places: 3.142
1 2 3 |
var pi = Math.PI; var formattedPi = $"Pi to three decimal places: {pi:.###}"; Console.WriteLine(formattedPi); |
This program below abides by the currency formatting and outputs: Total cost: $32.29
1 2 3 4 |
var price = 29.99; var taxRate = 0.08; var total = $"Total cost: {price * (1 + taxRate):C}"; Console.WriteLine(total); |
Here is an example with date formatting that outputs: Current date (custom format): 2024-Apr-17
1 2 |
DateTime now = DateTime.Now; Console.WriteLine($"Current date: {now:yyyy-MMM-dd}"); |
Alignment
Using the character ,
you can precise the alignment, for example:
1 2 3 4 |
var item = "apple"; var quantity = 5; Console.WriteLine($"Item: {item,10} | Quantity: {quantity,3}"); Console.WriteLine($"Item: {item,-10} | Quantity: {quantity,-3}"); |
This program outputs:
1 2 |
Item: apple | Quantity: 5 Item: apple | Quantity: 5 |
The alignment number indicates the number of characters allotted for displaying the string. If this number is positive, the string is right-aligned; if negative, it is left-aligned. Should the string exceed the length of the alignment number, the runtime doesn’t truncate it. This can cause misalignment when you display multiple lines.
New Lines in Interpolation Expression
Starting from C# 11, you can incorporate new lines within interpolation expressions to enhance code readability. The example below demonstrates how using new lines can make an expression involving pattern matching clearer:
1 2 3 4 5 6 7 8 |
string message = $"At {degreeCelsius}°C, the state of H2O is: { degreeCelsius switch { >= 100 => "Steam - Water has boiled and turned to vapor.", >= 0 => "Liquid - Water is in its liquid state.", _ => "Ice - Water has frozen and turned to solid ice.", } }"; |
Escaping Braces
To include literal curly braces in an interpolated string, double the character:
1 2 3 |
var count = 3; var message = $"{{This message includes {count} curly braces}}."; Console.WriteLine(message); |
This program outputs: {This message includes 3 curly braces}.
C# 11 introduces raw string literals. If you want to be able to use the characters {
and }
as-is, the interpolated strings need to be prefixed with $$
and the interpolated expressions need to use double curly braces {{item}}
. Here is a short sample program:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
string sister = "Léna"; string brother = "Paul"; Console.ForegroundColor = ConsoleColor.White; Console.BackgroundColor = ConsoleColor.DarkBlue; Console.WriteLine( $$""" { "sister": "{{sister}}", "brother": "{{brother}}", } """); Console.BackgroundColor = ConsoleColor.Black; Console.ReadKey(); |
This program outputs:
More than two $
characters can be used to prefix an interpolated string to use a sequence of curly braces as-is as illustrated below:
String Interpolation And Performance
Before C#10 and .NET 6 string interpolation was based on string.Format()
. Concretely this program:
1 2 |
string str = $"Welcome back, {name}! Today is {DateTime.Now:MMMM dd}, and it's a perfect day for coding."; |
…compiled into this:
1 2 3 4 |
string str = string.Format( "Welcome back, {0}! Today is {1:MMMM dd}, and it's a perfect day for coding.", name, DateTime.Now); |
This means that the formatting string gets parsed at runtime within the method Format()
each time it is called. This necessarily has a performance impact.
Since C#10 and .NET 6 the same interpolated string compiles into this:
1 2 3 4 5 6 7 |
DefaultInterpolatedStringHandler x = new DefaultInterpolatedStringHandler(61, 2); x.AppendLiteral("Welcome back, "); x.AppendFormatted(name); x.AppendLiteral("! Today is "); x.AppendFormatted(DateTime.Now, "MMMM dd"); x.AppendLiteral(", and it's a perfect day for coding."); string str = defaultInterpolatedStringHandler.ToStringAndClear(); |
The C# compiler eases the workload on the runtime by preprocessing the expressions and their formats within interpolated strings.
Also the C# compiler relies on System.Runtime.CompilerServices.DefaultInterpolatedStringHandler
that maintains internally a string buffer similarly to StringBuilder
. But it is more efficient due to being declared as a ref struct
in the Base Class Library (BCL). The use of ref struct
allows it to leverage the managed pointer capabilities of the runtime, enhancing performance. This design is also seen in types like Span<T>
, which are also defined as ref struct
.
For a deeper understanding of ref struct
, read this article: Managed pointers, Span, ref struct, C#11 ref fields and the scoped keyword.
For an in-depth coverage of compiler interpolated string handlers you can read String Interpolation in C# 10 and .NET 6 by Stephen Toub.
Conclusion
C# string interpolation offers a clean, readable syntax for incorporating variables and expressions into strings. It is suitable for most use cases and simplifies code, making it easier to read and maintain. Experiment with these examples to better understand and apply string interpolation in your own C# projects.