C# Raw String Literal Syntax and Use Cases
c# raw string literal: Learn how to use C# raw string literals for multiline text, JSON, and regex without escape sequences, including indentation rules and interpolat...
A C# raw string literal lets you write multiline text exactly as it appears in your source code, without escape sequences and without the line-continuation awkwardness of verbatim strings. Introduced in C# 11, raw strings are delimited by three or more double-quote characters ("""), and they change how you handle embedded quotes, backslashes, and indentation. If you have ever fought with escaping backslashes in a regular expression or formatting JSON in a string constant, this feature directly solves that problem.
Why Raw Strings Were Added to C#
Before C# 11, you had two main options for text that spans multiple lines: verbatim strings (prefixed with @) and regular strings with escape sequences. Verbatim strings handle backslashes and newlines well, but they treat quotes as special, so a quote must be doubled (""). Regular strings require escaping backslashes, quotes, and control characters, which becomes unreadable for text like file paths or JSON.
A common workaround was to build strings at runtime using arrays or string builders, which adds code that is hard to read. Raw string literals remove the need for most escaping because the compiler does not interpret backslashes or quotes inside the literal. The only escape sequence that works in a raw string literal is the interpolation $ when you use interpolation, and that is controlled by how many dollar signs you include.
Syntax and Delimiter Rules for Raw Strings
A raw string literal starts and ends with at least three double-quote characters. The number of quotes determines how many consecutive quotes can appear inside the literal. For example:
string simple = """This is a raw string.""";
If you need to include three consecutive quotes inside the text, you start and end with four quotes:
string withQuote = """"He said ""Hello"" to me."""";
Here the outer four quotes are the delimiters, and the inner "" sequences are treated literally. The rule is simple: the delimiter length must be greater than any sequence of consecutive quotes inside the content.
Raw string literals can span multiple lines. When they do, the closing delimiter must be on its own line, and the indentation of the closing delimiter determines how much leading whitespace is removed from every line. This is a key behavior that differs from verbatim strings.
string json = """ { "name": "sample", "enabled": true } """;
In this example, the closing delimiter is at column zero, so no indentation is removed. The resulting string contains no leading spaces on any line. If you indent the closing delimiter to match the surrounding code, the compiler strips that same indentation from every line.
Indentation Handling in Raw Strings
Indentation handling is the most subtle part of raw string literals. The content of a multiline raw string includes the newline after the opening delimiter and the newline before the closing delimiter. The compiler looks at the closing delimiter's indentation and removes that exact sequence of whitespace from the beginning of each line.
Consider this example:
var message = """ Line one Line two """;
The closing delimiter is indented with four spaces. The resulting string is "Line one\nLine two\n". The leading four spaces on each line are stripped. This makes raw strings work cleanly inside methods where the surrounding code is already indented.
A limitation is that every non-empty line must have at least the indentation of the closing delimiter. If a line has less indentation, the compiler raises an error. This prevents accidental misalignment and makes the behavior deterministic.
Interpolating Values in Raw String Literals
You can use string interpolation with raw string literals by adding one or more $ characters before the opening delimiter. The number of $ characters determines how many braces you need to use for an interpolation expression.
With one $, a single pair of braces is used:
string name = "Ada"; string greeting = $"""Hello, {name}!""";
With two $, you need two pairs of braces:
string name = "Ada"; string greeting = $$"""Hello, {{name}}!""";
This is useful when the content itself contains single braces, such as JSON or a code template. For instance, a JSON template that needs to inject a variable might look like this:
string id = "123"; string json = $$""" { "id": "{{id}}", "status": "active" } """;
The double braces in the content become literal braces in the output, and the {{id}} is replaced with the value of the id variable.
Practical Use Cases for Raw Strings
Raw strings shine in several practical scenarios. The most obvious is embedding JSON, XML, or HTML templates directly in source code without escaping every quote. For example, building a test fixture:
var requestBody = """ { "user": "alice", "role": "admin" } """;
Regular expressions are another strong case. A raw string lets you write a regex with backslashes exactly as they appear in the pattern:
var pattern = """\d{3}-\d{2}-\d{4}""";
This is much more readable than "\\d{3}-\\d{2}-\\d{4}". The raw string preserves the backslashes so the regex engine sees \d instead of a double-backslash.
Code generation is another area. If you are generating C#, SQL, or other code as string templates, raw strings allow you to keep the template readable and properly indented without string concatenation or StringBuilder.
Raw String vs Verbatim String: When to Use Which
Verbatim strings (@"...") are still the right choice for simple single-line strings that include backslashes, such as Windows file paths. They are concise and do not add the extra visual weight of triple quotes.
Raw strings are better when you have multiline content or content that contains many quotes, like JSON. Verbatim strings still require doubling quotes, which is easy to get wrong. Raw strings also handle indentation in a way that makes them suitable for embedding in source code, whereas verbatim strings do not automatically strip indentation.
| Feature | Verbatim string | Raw string literal |
|---|---|---|
| Backslash handling | Preserved | Preserved |
| Quote handling | Must double " | No escaping needed |
| Multiline | Yes | Yes, with indentation stripping |
| Interpolation | Supported | Supported with $ |
| Single-line | Yes | Yes |
A practical rule: if you have a single-line string with backslashes and no quotes, a verbatim string is fine. If your text is multiline or contains quotes that would need escaping, use a raw string.
Common Mistakes and Compiler Errors
One frequent mistake is forgetting that a multiline raw string includes the trailing newline. If you do not want the final newline, you have to design the literal accordingly, perhaps by keeping the content on one line.
Another mistake is using the wrong number of $ signs for interpolation. If the content contains single braces and you use one $, the compiler will try to interpret {...} as an interpolation expression and fail. Using two $ avoids this, but then a single brace is literal only if it is not doubled. The number of $ must match the brace style you want.
A third issue is inconsistent indentation. If a line in the raw string has less indentation than the closing delimiter, the compiler raises CS8999 (or a similar message depending on the compiler version). The fix is to align the content lines with the closing delimiter or reduce the closing delimiter's indentation.
Finally, remember that raw strings are a language feature requiring C# 11 or later. If you are targeting an older language version, the compiler will not recognize the syntax. You can check your project's <LangVersion> setting if you see errors about invalid tokens.
Runtime and Maintainability Considerations
From a runtime perspective, raw string literals are no different from other string literals. The compiler creates the string at compile time, so there is no runtime parsing cost. The only cost is the same as any string constant: one allocation for the object, and no repeated construction.
For maintainability, raw strings reduce the risk of escaping errors. When you update a JSON template or an SQL query, you can copy the actual content directly into the source instead of manually escaping it. This also makes the code easier to review because the literal matches the intended output.
One tradeoff is that raw strings can hide the actual string content in code review if the indentation rules are not well understood. A reviewer might see a multiline block and not realize that the leading whitespace is stripped. Clear formatting and consistent indentation mitigates this.
If your project targets older frameworks or languages, you need to weigh the benefit against compatibility. Raw strings require a compiler that supports C# 11, which means modern versions of Visual Studio and .NET SDK. They do not require any runtime support because the compiler generates ordinary System.String objects.
Advanced Pattern: Using Raw Strings for Code Templates
A common advanced pattern is using raw strings to define code templates in tools like source generators or scaffolding scripts. Because raw strings handle indentation cleanly, you can embed a template that itself contains indentation and braces without corrupting the output.
For instance, generating a class file:
string className = "Product"; string template = $$""" namespace Generated { public class {{className}} { public int Id { get; set; } } } """;
The template preserves the four-space indentation inside the namespace, and the interpolation inserts the class name. Without raw strings, this template would be full of escaped backslashes and doubled quotes if it contained string literals.
When working with source generators, you often need to build code as strings and then parse them. Raw strings make the templates more readable, which directly reduces bugs in the generated code.
Compatibility and Tooling Support
Raw string literals are supported in C# 11 and later. This means you need the .NET SDK 7 or later, or a compiler that supports the C# 11 language version. Visual Studio 2022 version 17.4 and later support this syntax. If you are using older tooling, the code will fail with syntax errors.
Most modern IDEs and editors handle raw strings well, offering syntax highlighting and even the correct indentation automatically. However, some older analysis tools or code formatters may not yet recognize the syntax, which could cause false warnings or formatting changes. Check your toolchain before adopting raw strings in a large codebase.
For teams that need to support older compilers, you must either upgrade the toolchain or continue using verbatim strings. Upgrading is usually straightforward, but if you maintain libraries that target multiple frameworks and use older language versions, raw strings cannot be used in those projects.
The indentation rule is also a point of care for code formatters. If a formatter adjusts the indentation of the closing delimiter, it changes the output string. This is a subtle maintenance risk, so it is wise to configure your formatter to respect the existing indentation of raw string delimiters.