Raw String Literals in C# 11

If you have ever embedded JSON in a C# string, you know the pain: escaped quotes everywhere, broken indentation, and code that is harder to read than the content it represents. C# 11 introduced raw string literals to solve this problem completely.

The Basics

A raw string literal starts and ends with at least three double-quote characters ("""). Everything between them is the string content, with no escape sequences processed:

Example.cs
var json = """
    {
        "name": "Alice",
        "age": 30,
        "active": true
    }
    """;

No escaping quotes. No @ prefix. The string looks exactly like the content it represents.

Indentation Handling

The closing """ determines the baseline indentation. Any whitespace to the left of the closing quotes is stripped from every line:

Example.cs
var html = """
    <div class="container">
        <h1>Hello</h1>
        <p>World</p>
    </div>
    """;
// Result has no leading spaces — the 4-space indent is removed

This means you can indent raw strings to match your code's structure without affecting the output. The closing delimiter acts as a left margin marker.

Single-Line Raw Strings

Raw strings do not require multiple lines. A single-line raw string uses """ on the same line:

Example.cs
var path = """C:\Users\Alice\Documents""";
// No need for @"C:\Users\Alice\Documents" or "C:\\Users\\Alice\\Documents"

This is particularly useful for file paths on Windows and regex patterns.

Interpolation with Raw Strings

Raw string literals support interpolation. The number of $ signs before the opening quotes determines how many braces are needed for an interpolation hole:

Example.cs
var name = "Alice";
var age = 30;

// Single $ — use single braces for interpolation
var message = $"""Hello, {name}! You are {age} years old.""";

// Double $$ — use double braces for interpolation
var jsonTemplate = $$"""
    {
        "name": "{{name}}",
        "age": {{age}}
    }
    """;

With $$, single braces {} are treated as literal text. This is essential for JSON, where braces are part of the content. You can use as many $ signs as needed — $$$ would require {{{expression}}} for interpolation, leaving { and {{ as literal text.

Handling Quotes Within Content

If your content contains """, simply use more quote characters for the delimiter:

Example.cs
var csharpCode = """"
    var greeting = """
        Hello, World!
        """;
    """";

Four quotes for the delimiter means three quotes in the content are treated as literal text. You can extend this to any number.

Practical Examples

SQL queries:

Example.cs
var query = """
    SELECT u.Name, u.Email, COUNT(o.Id) AS OrderCount
    FROM Users u
    LEFT JOIN Orders o ON u.Id = o.UserId
    WHERE u.CreatedDate > @startDate
    GROUP BY u.Name, u.Email
    HAVING COUNT(o.Id) > 0
    ORDER BY OrderCount DESC
    """;

Regex patterns:

Example.cs
var emailPattern = """^[\w.+-]+@[\w-]+\.[\w.]+$""";
// No need to escape backslashes

XML configuration:

Example.cs
var config = """
    <?xml version="1.0" encoding="utf-8"?>
    <configuration>
        <appSettings>
            <add key="ApiUrl" value="https://api.example.com" />
            <add key="Timeout" value="30" />
        </appSettings>
    </configuration>
    """;

Test data:

Example.cs
[Theory]
[InlineData("""{"valid": true}""", true)]
[InlineData("""{"valid": false}""", false)]
public void ShouldParseValidFlag(string json, bool expected)
{
    var result = JsonSerializer.Deserialize<Payload>(json);
    Assert.Equal(expected, result!.Valid);
}

Comparing String Literal Types

C# now has four string literal forms:

Example.cs
// Regular — supports escape sequences
var a = "Hello\nWorld";

// Verbatim — no escape sequences except "" for quotes
var b = @"C:\Users\Alice";

// Raw — no escaping, indentation control
var c = """
    No "escaping" needed
    """;

// Raw interpolated — combines raw with interpolation
var d = $$"""
    {"value": {{computedValue}}}
    """;

When to Use Raw String Literals

Use raw strings whenever your content contains characters that would need escaping in a regular string. The most common cases are:

Raw string literals are one of those features that, once you start using, you wonder how you managed without. They make embedded content readable and maintainable, eliminating an entire category of escaping bugs.