C# 11 introduces Raw String Literals. Undoubtedly this feature will become very popular because it represents an elegant way to solve some issues with actual string literal.
Let’s have a look at such raw string literal with interpolation. Notice that a raw string literal necessarily starts and ends with at least 3x double quote characters """
.
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(); |
We use console coloring to highlight the string obtained at runtime:
We can see that C# 11 raw string literal has three major impacts on:
- Formatting and Alignment: for example there are 6 white spaces before the character
{
in the literal that are skipped by the compiler. - Double quote character
"
that so far couldn’t be declared as-is in a string literal. To obtain the 3 characters string-"-
we had to either use this literal"-\"-"
or this one@"-""-"
. - Interpolation: this string literal is relying on string interpolation but interpolation delimiters are
{{
and}}
and the single character{
is declared as-is, which was not possible so far in an interpolated string.
Let’s detail these three various impacts one by one:
Formatting and Alignment in Raw String Literals
Let’s slightly modify the small program above:
- First we remove a space just before the
"""
end delimiter. In the output we can see that the string resulting from compilation is aligned with the end delimiter column. We can also see that the Visual Studio editor shows a vertical gray line that indicates what the string resulting from compilation will be. - Second we add a line before the
"""
end delimiter line and it contains a single whitespace (selected in code for clarity). Despite being made of only whitespaces, this extra line is included in the string resulting from compilation.
Clearly C# 11 raw string literal is a great way to declare much clearer JSON, XML, SQL, test expectations… string literals in code thanks to alignment with the actual nesting:
Let’s challenge this new string literal alignment feature. First only whitespace characters are accepted in columns before the column of the """
end delimiter
Second the begin and end delimiter’ lines can only accept whitespace characters. These whitespace characters are skipped by the compiler. Let’s underline that delimiters can be on the same line for single line literals: """this is a single line raw string literal"""
.
Sequences of double quote ” characters in Raw String Literals
A raw string literal necessarily starts and ends with at least 3x double quote characters """
. At least is in bold because more than three double quote characters can be used for delimiters. With the """
delimiter the literal can contain "
and ""
sub-strings. With the """"
delimiter the literal can contain "
, ""
and """
sub-strings. And so on…
This astute of an extra double quote in delimiter is quite nifty if you ask me : It thoroughly solves the ugly back-slashing \"
and double double-quote character ""
in string literals.
Here is the plain-text code if needed:
1 2 3 4 |
Assert.AreEqual( """-"hello"-""" , "-\"hello\"-"); Assert.AreEqual( """-""hello""-""" , "-\"\"hello\"\"-"); Assert.AreEqual( """"-"""hello"""-"""" , "-\"\"\"hello\"\"\"-"); Assert.AreEqual("""""-""""hello""""-""""", "-\"\"\"\"hello\"\"\"\"-"); |
Interestingly enough three consecutive double quote characters """
was never a valid expression in C# 10 and earlier so there is no risk of breaking existing code. Also two consecutive double quote characters ""
was (and remains) the expression for the empty string so it couldn’t be used for raw string literal delimiters.
Interpolation in Raw String Literals
The same astute is used for interpolation brace in string literal. In interpolated string so far a {
or }
brace character required a double braces sequence, {{
or }}
. Now the number of leading dollar character $
, determines the number of brace characters the literal can contain without being considered as an interpolation expression delimiter. This code gets clearer with the Visual Studio editor highlighting:
Here is the plain-text code if needed:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
string sister = "Léna"; // All those string literals are equals to the value of sister string Assert.AreEqual( $"{sister}" , sister); Assert.AreEqual( $"""{sister}""" , sister); Assert.AreEqual( $$"""{{sister}}""" , sister); Assert.AreEqual( $$$"""{{{sister}}}""" , sister); Assert.AreEqual($$$$"""{{{{sister}}}}""", sister); // $$ interpolation string prefix means that // -> the string literal can include single '{' or '}' characters // -> {{ }} are delimiter for the interpolationExpression Assert.AreEqual($$"""{sister}""" , "{sister}"); Assert.AreEqual($$"""{{{sister}}}""" , "{Léna}"); // $$$ interpolation string prefix means that // -> the string literal can include "{{" or "}}" sequences // -> {{{ }}} are delimiter for the interpolationExpression Assert.AreEqual($$$"""{{sister}}""" , "{{sister}}"); Assert.AreEqual($$$"""{{{{{sister}}}}}""" , "{{Léna}}"); // $$$$ interpolation string prefix means that // -> the string literal can include "{{{" or "}}}" sequences // -> {{{{ }}}} are delimiter for the interpolationExpression Assert.AreEqual($$$$"""{{{sister}}}""" , "{{{sister}}}"); Assert.AreEqual($$$$"""{{{{{{{sister}}}}}}}""", "{{{Léna}}}"); |
Enjoy
good update to continue exploring, but first let me search for “Lena Paul”