Cover

C# 11 Strings in the Raw

November 26, 2022
No Comments.

With the release of C# 11, there is a new string in town. It might be getting crazy, but this new “Raw String Literals” is something interesting. Before we dig in, let’s have a refresher about strings:

Simple Strings

Every language needs a type for storing text, that’s the String class/string keyword. It’s what is used mainly in C# and has been there since day 1:

var text = "I thought we had literal strings";
WriteLine(text);

We could use embedded quotes, but we needed to escape them (or other things like tabs, line breaks):

text = "John \"Quincy\" Adams";

We didn’t have a good solution for multi-line, so we ended up with monstrosities (or using a StringBuilder):

text = "First Line\n";
text += "Second Line\n";
text += "Third Line";

String Interpolation

Some time, later C# introduced a way to have strings just use interpolation (instead of the dreaded string.Format(…)):

text = $"This is an interpolated string: {someName} - {someName.Length}"; 

The dollar sign said that it should expect C# code inside brackets.

But this introduced a need to double bracket if you needed a bracket in string:

text = $"This is an interpolated string: {{ {someName} }}"; 

A compromise to support this better way of building strings. Of course, that made JSON in strings pretty ugly:

text = $"{{ \"name\": \"Shawn\" }}";

Verbatim Strings

In came Verbatim strings. This allowed you to have line breaks and look simpler:

text = @"This is a verbatim string.

This means you can have line breaks 
and use double ""'s to output quotes.";

While many things didn’t need to be escaped, you still needed something special for double-quotes. If you needed double-quotes you had to double them to get:

This is a verbatim string.

This means you can have line breaks
and use double "'s to output quotes.

Not perfect, but worked in a lot of situations, but if you wanted to use a format like XML or JSON, it ended up with this ugliness:

text = @
{
  ""name"": ""Shawn"
}
";

Verbatim Strings with Interpolation

But you could mix verbatim and interpolation:

text = $@"This is a verbatim 
interpolated string: {someName}";

This worked, unless you needed brackets as text:

// Doesn't work, as it thinks that the whole thing is interpolated
text = $@"
{ 
  ""name"": ""{someName}"" 
}";

So, now we need to double-quote as well as double curly-brace:

// Works
text = $@"
{{ 
  ""name"": ""{someName}"" 
}}";

Hrmph…

Ok, Raw String Literals?

Here’s where Raw String Literals come in. The idea is to allow anything between a set of delimiters. That delimiter is a triple-quote (yes, seriously, but it does make sense).

When you triple-quote, everything is a literal, No magic here:

text = """This is pure text, which includes " and ' and other literals""";

This works, but the rules are a tad different for multi-line, in that case the triple-quotes must be on their own lines:

text = """
Everything between the quotes is literally interpreted, 
There is no need for escaping of anything.

Really!
  You can use "Whatever you Like"
""";

What’s important here is that the triple-quoted lines are not included in the string. The string starts on the first line after the triple-quote. This solves a lot of the messiness with commonly used things like JSON:

text = """
{
  "name": "Shawn"
}
""";

Whew, that’s easy…almost.

Interpolated Raw String Literals?

If you add interpolation to a raw string, you find an odd situation where the compiler must know what is an interpolated section (Raw String Literals assume everything is just text). Like the other types of strings, you start interpolated strings with a dollar sign:

text = $"""<name>{someName}</name>""";

Simple, sure. But what if you need brackets?

// Doesn't work, as it's expecting the brace
// to be part of the interpolation
text = $""" 
{
  "name": "{someName}"
}
""";

The solution? To do interpolation with brackets, the number of dollar-signs represents the number of brackets to indicate an interpolation:

// Add number of $ for the depth of the braces needed
text = $$"""
{
  "name": "{{someName}}"
}
""";

This isn’t a typo, this is valid C# 11. Solves a ton of situations, but still requires you to remember some stuff (I actually wish that had used the back-tick like JavaScript as it reads easier IMO).

What do you think of new new syntax (and do you think you’ll be using it?) Tell me in the comments!