C# 11.0: Raw String Literals
In November 2022, .NET 7.0 was released, and since then, you can use C# 11.0.
In version 11.0, the C# language got a bunch of new features. I want to explore the new features I’m most excited about together with you in a series of blog posts. Let’s start in this blog post with a feature called Raw String Literals.
Before we look at Raw String Literals, let’s look at the evolution of strings in C# and let’s start with C# 1.0. All these concepts are still valid today with C# 11.0, and it’s always good to remember the basics. Let’s go! :)
Quoted String Literals in C# 1.0
Since C# 1.0, you can declare and initialize a string like this:
string firstname = "Thomas";
This is actually a quoted string literal, as it starts and ends with a single double quote. Quite often a quoted string literal is also referred to as regular string literal.
With a backslash, you can declare so-called escape sequences. Let’s say you want to define the string Hello "Thomas"
, including the quotes. As a quote normally defines the end of the string, you have to define a quote inside of the string with an escape sequence. Such an escape sequence starts with a backslash, and for a quote you use \"
. So, to define the string Hello "Thomas"
, you write this:
string welcomeMessage = "Hello \"Thomas\"";
Or to define a carriage return you use \r
, and for a new line you use \n
. So, this string will put the name Huber on a new line:
string fullname = "Thomas Claudius\r\nHuber";
There are several other escape sequences for C# strings. But it gets really interesting when it comes to filepaths and folderpaths, as these usually contain backslashes by default on Windows. But you just saw that a backslash is used to start an escape sequence. So, by default C# looks for a specific character after the backslash, like n
for a new line. To use a backslash in a string, you have to escape it with another backslash. Like you use \"
to define a double quote, you use \\
to define a backslash. To define a string with the value C:\Users\Thomas\Documents
, you use the following statement:
string folderPath = "C:\\Users\\Thomas\\Documents";
Now, this brings us to the next string literal type, the verbatim string literals.
Verbatim String Literals in C# 1.0
A verbatim string literal starts with @"
. It is great if your string contains backslashes, quotes, or multiple lines. Look at the following folderPath. You can use the backslash in the verbatim string literal like a normal character, as the verbatim string literal does not look for escape sequences that start with a backslash:
string folderPath = @"C:\Users\Thomas\Documents";
Also for multi-line strings, verbatim string literals are good. The following two string variables have exactly the same content, but for the first, a quoted string literal is used to define it, for the second, a verbatim string literal is used:
// Quoted string literal
string fullname1 = "Thomas\r\nClaudius\r\nHuber";
// Verbatim string literal
string fullname2 = @"Thomas
Claudius
Huber";
To define a double quote inside a verbatim string literal, you just write two double quotes (as a single one ends the string). The following snippet shows this. Again, both variables contain the same string, Hello "Thomas"
:
// Quoted string literal
string welcomeMessage1 = "Hello \"Thomas\"";
// Verbatim string literal
string welcomeMessage2 = @"Hello ""Thomas""";
Concatenate and Format Strings in C# 1.0
To use C# variables within a string, you can concatenate strings like you see it below with the +
character. The fullName
variable contains now the string Thomas Huber
:
string firstName = "Thomas";
string lastName = "Huber";
string fullName = firstName + " " + lastName;
Alternatively, you can use the string.Format
method to use variables in a string like you see it below. Also here, the fullName
variable contains the string Thomas Huber
.
string firstName = "Thomas";
string lastName = "Huber";
string fullName = string.Format("{0} {1}", firstName, lastName);
Declare Strings with var in C# 3.0
Nothing really changed in C# 3.0 for strings. But since then, you can use the var
keyword to declare and intialize local string variables. The type of the variable is implicitly inferred from the assigned value, which is in this case a string:
var firstname = "Thomas";
String Interpolation in C# 6.0
With C# 6.0, Microsoft introduced string interpolation. This makes the use of C# variables and expressions within a string easier. Before C# 6.0, you had to concatenate strings with the +
character or you had to use the string.Format
method like explained already in this blog post.
Since C# 6.0, you can use string interpolation. An interpolated string starts with a $
sign and then you can use {
and }
to include C# variables and expressions in the string. The following initialization of the fullName
variable demonstrates this, and it also leads to the string Thomas Huber
:
var firstName = "Thomas";
var lastName = "Huber";
var fullName = $"{firstName} {lastName}";
Instead of using simple variables, you can also use expressions with string interpolation. The following snippet uses the +
operator to add two numbers in the expression of an interpolated string. The variable task
will contain the string 2+3=5
.
int num1 = 2;
int num2 = 3;
var task = $"{num1}+{num2}={num1 + num2}"; // Results in the string "2+3=5"
String interpolation works of course not only with quoted string literals, but also with verbatim string literals. Start your string with $@"
to use string interpolation in a verbatim string literal. The following snippet shows this:
var username = "Thomas";
var folderPath = $@"C:\Users\{username}\Documents";
Things get a bit more interesting if you want to use curlies in your quoted or verbatim string literal that uses string interpolation. Because with string interpolation, curlies in your string are now used for C# variables and expressions. If you want to have a curly in your output string, you define two curlies in the string literal. Let’s say you want to define the string {Hello} Thomas
when using string interpolation. You do that like you see it below. Note the two opening and closing curlies around the word Hello in this snippet:
var username = "Thomas";
var welcomeMessage = $"{{Hello}} {username}"; // {Hello} Thomas
The Downsides of Quoted and Verbatim String Literals
There are a few downsides with quoted and verbatim string literals. The in my opinion biggest one is that you can never write your string in code exactly like it looks in the output if there are special characters like for example double quotes. This means that you cannot copy and paste a string into the code editor like for example the JSON below:
{
"firstName":"Thomas",
"lastName":"Huber"
}
When you want to store this JSON string with a quoted string literal, including the linebreaks, you have to write it like this:
var json = "{\r\n \"firstName\":\"Thomas\",\r\n \"lastName\":\"Huber\"\r\n}";
When you use the json string with a verbatim string literal, you have to write it like this:
var json = @"{
""firstName"":""Thomas"",
""lastName"":""Huber""
}";
The verbatim string literal is quite close, but as you can see in the code snippet above, you still have to double each double quote (Sounds great, doesn’t it? “Double each double quote”. :))
The verbatim string literal has also the disadvantage that it includes all the whitespace on the left when you use multiple lines. This means you have to write your string lines on the left side of the source file if you don’t want to get all that whitespace. This problem gets more clear when your code has some nesting. In the following snippet, there is a verbatim string literal inside of a method that is inside of a class that is inside of a namespace. You can see how the lines of the verbatim string literal are on the left, so that the JSON string looks exactly like defined in the snippet at the beginning of this section.
namespace MyNamespace
{
public class MyClass
{
public string GetJson()
{
var json = @"{
""firstName"":""Thomas"",
""lastName"":""Huber""
}";
return json;
}
}
}
Now, all these downsides of quoted and verbatim string literals are solved with raw string literals, a new feature of C# 11.0. Let’s dive into it.
Raw String Literals in C# 11.0
A raw string literal is a new type of string literals. It allows you to write strings exactly in the way how you want to store them. This means you can copy and paste any string and use it as it is without adding any escape sequences. You can use the raw strings in your code.
How does this work?
A raw string literal starts with minimum three double quotes, and it ends with the same number of double quotes. The following snippet shows you the three string literal types, and all are defining the string Thomas
:
// Quoted string literal
var firstname1 = "Thomas";
// Verbatim string literal
var firstname2 = @"Thomas";
// Raw string literal
var firstName3 = """Thomas""";
Now, of course, for such a simple string without any special characters, there’s no need to use a raw string literal, the quoted string literal is the best choice here. Before we look at another sample, I want to show you one more thing with raw string literals.
Normally, you add a line break after the three double quotes that start the string, and you add another one before the three double quotes that close the string. You see this in the code snippet below. The final string does not contain these linebreaks. Also, the whitespace on the left is removed. The horizontal start position of the closing """
defines where whitespace is removed for all lines above. In the following snippet you see that the string Thomas
is horizontally exactly above the closing """
. This means the whitespace on the left of Thomas
is not part of the string. This means also that both variables in the codesnippet below contain exactly the same string, which is the string Thomas
. Note how in this case the linebreaks at the beginning and at the end of the raw string literal are removed, and how also the white space on the left is removed.
// Quoted string literal
var firstname1 = "Thomas";
// Raw string literal
var firstName2 = """
Thomas
""";
Now let’s say you want to define the string Hello "Thomas"
. Look in the snippet below how you can use that string exactly as it is with the raw string literal:
// Quoted string literal
var welcome1 = "Hello \"Thomas\"";
// Verbatim string literal
var welcome2 = @"Hello ""Thomas""";
// Raw string literal
var welcome3 = """
Hello "Thomas"
""";
Using more double quotes
Now, let’s imagine you want to create a string that has three double quotes in a row like this one: Hello """Thomas"""
. Then the rule is that your raw string literal must start and end with at least one more double quote than the content. In this case it means your raw string literal needs to start and end with at least four double quotes, as the content has already three double quotes:
var firstName = """"
Hello """Thomas"""
"""";
I mean, you could also add many more double quotes to start and end your raw string literal like below, that’s also still valid code, but just one more than the content is enough as long as you’re not paid by the number of double quotes in your code:
var firstName = """""""
Hello """Thomas"""
"""""""; // You could start and end here with just 4 double quotes
String interpolation with Raw String literals
Raw string literals support also string interpolation. As with quoted and verbatim string literals, you use the $ sign to do this. Below is a snippet that shows how to create the string Hello "Thomas"
:
var firstName = "Thomas";
var welcome = $"""
Hello "{firstName}"
"""; // Hello "Thomas"
Now, what if you want to create the string {Hello} "Thomas"
? This means your raw string contains curlies. How does the C# compiler know if those curlies start a C# variable/expression or are part of the content? Raw string literals have also a solution for this. You can use two $$
signs, and then within the string you need to use {{ }}
to include a C# variable/expression. Just a single {
and }
is then seen as content. The following snippet defines the string {Hello} "Thomas"
. Note the two $$
at the beginning and the two {{
and }}
used to use the firstName
variable in the interpolated string.
var firstName = "Thomas";
var welcome = $$"""
{Hello} "{{firstName}}"
"""; // {Hello} "Thomas"
Now, also here for the curlies, the same rules as for the double quotes apply. You should use one more $
sign than you have curlies in a row in your raw string. Let’s say you want to define the string {{{Hello}}} "Thomas"
with an interpolated string. You need four $$$$
and four {{{{
to start the C# expression, as the content contains already three {{{
in a row. The following snippet shows this in action:
var welcome = $$$$"""
{{{Hello}}} "{{{{firstName}}}}"
"""; // {{{Hello}}} "Thomas"
Let’s Look at the JSON
In this blog post, we had already the following little JSON document as an example:
{
"firstName":"Thomas",
"lastName":"Huber"
}
With a raw string literal, you can define it like below, and you see, the JSON in the C# code looks exactly like the JSON that you want to store in the string variable. No need to escape anything in this string.
var json = """
{
"firstName":"Thomas",
"lastName":"Huber"
}
""";
To use string interpolation in this JSON, you have to use two $$
signs, as the JSON document contains curlies. This means that you start your C# variables and expressions with {{
and you end them with two }}
. The snippet below shows this:
var firstName = "Thomas";
var lastName = "Huber";
var json = $$"""
{
"firstName":"{{firstName}}",
"lastName":"{{lastName}}"
}
""";
As I mentioned already before, the closing double quotes of a raw string literal define the horizontal position from where on all white space is removed for the lines before. The following picture illustrates this.
This means, you have to put all the content of your raw string literal either exactly above the closing double quotes, or more to the right. If your string lines are more left than the closing double quotes, you’ll get an error in the code editor.
Now, this whitespace feature means that, unlike with verbatim string literals, you don’t have to move your multi-line strings to the left side of the code file anymore to get the output string with the expected whitespace. Look at the following verbatim string literal (that you saw already in this blog post) where everything is on the left, so that the json string does not contain unintended whitespace on the left:
namespace MyNamespace
{
public class MyClass
{
public string GetJson()
{
var json = @"{
""firstName"":""Thomas"",
""lastName"":""Huber""
}";
return json;
}
}
}
The snippet above looks ugly, as you can’t indent the multi-line verbatim string literal into the GetJson
method, because then the string would contain all the whitespace on the left.
As you just learned, in raw string literals, the closing double quotes define the horizontal position from where the whitespace for the multi-line string starts. This means, you can write that GetJson
method nicely indented like below, and even the JSON looks exactly like you want it in the output, no doubled double quotes as with the verbatim string literal are required:
namespace MyNamespace
{
public class MyClass
{
public string GetJson()
{
var json = """
{
"firstName":"Thomas",
"lastName":"Huber"
}
""";
return json;
}
}
}
Looks awesome, I love it!
Summary
You learned in this blog post about the new raw string literals. They let you define any string exactly like it should be stored in the variable. This means you can copy and paste huge string values and use them as they are, without having to escape any special characters. I think it’s a fantastic new feature for C#, and I’m sure for many multi-line strings I’ll use raw string literals instead of verbatim string literals that start with @"
. But I think, for filepaths, the verbatim string literal is still my favorite, or what do you think:
// Quoted string literal
var filePath1 = "C:\\Users\\\Thomas\\\Documents";
// Verbatim string literal
var filePath2 = @"C:\Users\Thomas\Documents";
// Raw string literal
var filePath3 = """C:\Users\Thomas\Documents""";
Alright! I hope you enjoyed reading this blog post.
In the next blog post, you will learn about Generic Attributes in C# 11.0.
Leave a Reply