Adventures in String Concatenation: Introducing String Interpolation

C# 6 has been out for quite some time now and I thought I would write up a quick post on one of its newer features that I use quite often: string interpolation.

What is String Interpolation?

String Interpolation isn't really anything new per-say, it just provides a way of building strings in a somewhat readable fashion, devoid of endless trails of '+' characters and indexed placeholders.

Let's take a look at a few ways that you might actually concatenate strings and we can see where string interpolation might come in.

The Classic Approach: Concatenation

I'm sure every developer reading this blog at one point or another has chained tons of strings together with the concatenation operator '+' as seen below :

string a = "Han";  
string b = "shot";  
string c = "first";  
// Build your string
var sentence = a + " " + b + " " + c + ".";  

While this is fairly common, it is far from ideal. Concatenating a series of strings like this can yield all sorts of unexpected work for the compiler to do, but there really isn't anything wrong with it.

If you want to give the compiler a break and do some of the work yourself, then you can use the String.Concat() method. This method accepts a set of parameters and does exactly what you would imagine, it concatenates them efficiently :

string a = "Han";  
string b = "shot";  
string c = "first";  
// Build your string
var sentence = String.Concat(a," ",b," ",c,".");  

This gets a bit trickier when you get into loops as the compiler may not be able to perform as much optimization as it would otherwise like. This is where the StringBuilder class comes in. StringBuilders allow you to continually and efficiently build a string without generating potentially hundreds of individual strings to do so.

You would simply instantiate an instance of the StringBuilder class and then use methods like Append() and AppendLine() to add to your string, until finally outputting your end result via a ToString() call :

var sb = new StringBuilder();  
for(var x = 1; x <= 5; x++)  
var result = sb.ToString();  

Even Better: Formatting

In a scenario like we defined earlier, concatenation really isn't ideal. This is primarily true because we have values that we are repeating (they are just spaces in this example, but they could not be) and are thus just wasting precious memory defining them just to be concatenated.

The String.Format() method solves this issue by allowing us to build a "formatting string" that uses placeholders to define where additional parameters will be added to the string. It's not only more efficient than concatenating a large number of strings, but it can be quite readable as well :

string a = "Han";  
string b = "shot";  
string c = "first";  
// Build your string
var sentence = String.Format("{0} {1} {2}.",a,b,c);  

As you can see, this doesn't look like much, but if we wanted to expand it a bit, you could see how it might be more useful :

var sentence = String.Format("{0} {1} {2}; {0} shot Greedo.",a,b,c);  

Meet String Interpolation

If there was any one of these options that the String Interpolation feature is going to replace, it's going to be the String.Format() method. In fact, you could almost think of it as a short-hand method for doing so.

The idea behind string interpolation is that it removes the pesky placeholders found in String.Format() calls and actually even removes any method calls at all. The Roslyn compiler will do all of the work when it recognizes what is going on.

Let's take a look at our previous example again :

var sentence = String.Format("{0} {1} {2}; {0} shot Greedo.",a,b,c);  

This would simply result in "Han shot first; Han shot Greedo.". Now those placeholders aren't exactly pleasing to the eye, so let's replace this call with how it would be handled using String Interpolation :

var sentence = $"{a} {b} {c}; {a} shot Greedo.";  

That's it. Just append a '$' to the beginning of your string and include your variables within the placeholders.

Roslyn will actually read the values and map the variable names to their appropriate placeholders. Additionally, these same placeholders will support all of the common formatting strings that are used for DateTime or numerical input as well :

var date = new Date(1977,5,25);  
var shooter = "Han";  
var victim = "Greedo";  
var shots = 42;  
var sentence = $"{shooter} shot {victim} {shots} times on a {date:dddd}.";  

This would output "Han shot Greedo 42 times on a Wednesday". But string interpolation isn't limited just to your normal formatting strings, you can also use some logic :

var sentence = $"{shooter} shot {victim} {(shots > 1 ? shots + " times" : "once")} on a {date:dddd}.";  

This would output "Han shot Greedo 42 times on a Wednesday", however if you changed shots to 1, then it would read "Han shot Greedo once on a Wednesday".

Pretty neat.

It's not a hammer.

While this new feature is something that I find myself using more and more, it isn't an all-out replacement for some of the other approaches. All of the operators and methods that were previously mentioned will work just fine and have their own strengths.

Personally, the most common uses for String Interpolation have been involving entities or objects and referencing properties of them similar to :

var widget = WidgetFactory.GenerateWidget();  
Console.WriteLine($"Widget {widget.ID} was made on {widget.BuildDate}");  

The most important thing to take away from this is the following: do not to compromise the readability of your code over things like formatting strings. If you find a case where this feature might be useful, then take advantage of it, but don't try to wedge it in, especially at the sake of readability.

More about Strings

If you want some extended reading on Strings in general, discussions on concatenation, performance and more, check out some of these resources :

comments powered by Disqus