C# 6 string interpolation is not a templating engine, and it’s not the new String.Format

One of the neat features in the new C# 6 is string interpolation, which is a concise way to inject values into a format string, using curly-brace-enclosed expressions. Here’s a simple example of what it looks like:

var url = $"http://weblogs.asp.net/{blog}/{slug}";

This is looking pretty good, and will likely simplify a lot of C# code going forward. It is however easy to get carried away and mistakenly think the feature is doing more than it does, and is designed for more diverse scenarios, where this sort of very explicit token insertion would also make sense. In this post, I’ll explore what the feature exactly is, and then I’ll show a few things it is not.

Let’s start with what it is. String interpolation is a more convenient syntax for mixing string literals with expressions. It’s code embedded in a string literal. As such, it needs to be expressed in the scope where the expressions are going to make sense. For instance, the example above is a replacement for:

var url = "http://weblogs.asp.net/" + blog + "/" + slug;

In the same way that you would never write this where “blog” and “slug” are not defined, you can’t write the string interpolation version either: the compiler will just scream at you.

That’s because the literal is parsed at compile-time, which also means that the string interpolation can’t be used on non-literal strings. That alone creates strong constraints on the scope of the feature.

In theory, you can use string interpolation every time you are feeding a literal string into String.Format, or concatenating literal strings and expressions. Such legitimate scenarios includes URL building like above (with sanitized or safe pedigree token values), and similar path building exercises where the format string is not English, but rather a technical kind of string.

That’s not to say that all String.Format scenarios could be moved to interpolation. Most other scenarios for String.Format involve human language. As such, the format string should be localizable. That means that it should not be embedded in the code as a string literal, but should instead be loaded from a satellite assembly, or a resource file or database. Thus, no string interpolation, and authors will still have to deal with numerically indexed formats, such as “The price of {0} is {1:C}.”, rather than an arguably better-looking “The price of {product} is {price:C}.”.

One could build a better String.Format that does that:

Console.WriteLine(localizationHelper.Format(
    "The price of {product} is {price}.",
    new {
        product = "Raspberry Pi",
        price = 25.0
    }
));

But this is not C# 6 string interpolation… Now you could improve on the API a bit using string interpolation, by implementing Format this way:

public string Format(FormattableString fs)
{
    // Get localized version of the default language string:
    var localFormat = GetLocalized(fs.Format);
    // Feed the resulting format string into String.Format:
    return String.Format(localFormat, fs.GetArguments());
}

This helps because you can now do away with the anonymous object and write this instead:

var product = "Raspberry Pi";
var price = 25.0;
Console.WriteLine(LocalizationHelper.Format(
    $"The price of {product} is {price}.";
));

However, the string interpolation will be compiled to a FormattableString with “The price of {0} is {1:C}” as the format that will get passed to GetLocalized. In other words, the people doing the localization will still have to localize with numeric indices instead of the more readable named tokens.

Another scenario where it looks like string interpolation could be useful –but isn’t– is templating. Templating is about building potentially large documents (usually HTML) with placeholders for expressions. It’s a complex problem, that involves tricky parsing, with lots of context changes, and strong requirements on encoding. String interpolation is simply not designed for that, even if the problem of requiring code-embedded literal strings wasn’t enough of a reason not to consider it. There are plenty of very good templating engines out there that you can use. Do that.

In summary, string interpolation is a useful improvement to the language, that will make a lot of code look more fluid. Its scope however, is restricted, and many scenarios that look superficially tempting are under closer analysis out of the question. So take it for what it is, and enjoy!

Thanks to Mads Torgersen for helping me better understand the feature.

1 Comment

Comments have been disabled for this content.