Skip to content

Commit a55249e

Browse files
BillWagnerCopilot
andauthored
Add tip for interpolated string parsing (#48946)
* Add tip for interpolated string parsing Fixes #43758 Add an include file with a tip that explains how Visual Studio and the C# Dev Kit interpret raw string literals and provides syntax coloring or potential fixes when the literal doesn't represent valid syntax for the chosen format. Add that include file in articles that provide information on raw string literals. Perform an edit pass and freshness pass on impacted articles. * Update docs/csharp/includes/raw-string-parsing.md Co-authored-by: Copilot <[email protected]> * Update docs/csharp/includes/raw-string-parsing.md --------- Co-authored-by: Copilot <[email protected]>
1 parent a3bb2af commit a55249e

File tree

6 files changed

+43
-18
lines changed

6 files changed

+43
-18
lines changed
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
---
2+
author: BillWagner
3+
ms.author: wiwagn
4+
ms.topic: include
5+
ms.date: 10/07/2025
6+
---
7+
> [!TIP]
8+
> Visual Studio and the C# Dev Kit provide some validation and syntax highlighting when raw string literals contain JSON data or regular expressions.
9+
>
10+
> The tools parse the text. If the tools have confidence that the text represents JSON or a regular expression, the editor provides syntax coloring.
11+
>
12+
> You can improve that experience by adding a comment above the declaration indicating the format:
13+
>
14+
> - `// lang=json` indicates the raw string literal represents JSON data.
15+
> - `// lang=regex` indicates the raw string literal represents a regular expression.
16+
>
17+
> When a raw string literal is used as an argument where the parameter uses the <xref:System.Diagnostics.CodeAnalysis.StringSyntaxAttribute?displayProperty=fullName> to indicate a format, these tools validate the raw string literal for some of the format types. Both JSON and regex are supported.
18+
>
19+
> For some formats, the comment or the attribute enables code suggestions offer fixes for string literals based on the format.

docs/csharp/language-reference/builtin-types/reference-types.md

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
---
22
title: "Built-in reference types"
33
description: "Learn about reference types that have C# keywords you can use to declare them."
4-
ms.date: 08/16/2022
4+
ms.date: 10/07/2025
55
f1_keywords:
66
- "object_CSharpKeyword"
77
- "object"
@@ -28,7 +28,7 @@ C# has many built-in reference types. They have keywords or operators that are s
2828

2929
## The object type
3030

31-
The `object` type is an alias for <xref:System.Object?displayProperty=nameWithType> in .NET. In the unified type system of C#, all types, predefined and user-defined, reference types and value types, inherit directly or indirectly from <xref:System.Object?displayProperty=nameWithType>. You can assign values of any type (except `ref struct`, see [ref struct](ref-struct.md)) to variables of type `object`. Any `object` variable can be assigned to its default value using the literal `null`. When a variable of a value type is converted to object, it's said to be *boxed*. When a variable of type `object` is converted to a value type, it's said to be *unboxed*. For more information, see [Boxing and Unboxing](../../programming-guide/types/boxing-and-unboxing.md).
31+
The `object` type is an alias for <xref:System.Object?displayProperty=nameWithType> in .NET. In the unified type system of C#, all types, predefined and user-defined, reference types and value types, inherit directly or indirectly from <xref:System.Object?displayProperty=nameWithType>. You can assign values of any type (except `ref struct`, see [ref struct](ref-struct.md)) to variables of type `object`. Any `object` variable can be assigned to its default value using the literal `null`. When a variable of a value type is converted to object, it's *boxed*. When a variable of type `object` is converted to a value type, it's *unboxed*. For more information, see [Boxing and Unboxing](../../programming-guide/types/boxing-and-unboxing.md).
3232

3333
## The string type
3434

@@ -55,7 +55,7 @@ string a = "good " + "morning";
5555

5656
The preceding code creates a string object that contains "good morning".
5757

58-
Strings are *immutable*--the contents of a string object can't be changed after the object is created. For example, when you write this code, the compiler actually creates a new string object to hold the new sequence of characters, and that new object is assigned to `b`. The memory that had been allocated for `b` (when it contained the string "h") is then eligible for garbage collection.
58+
Strings are *immutable*--the contents of a string object can't be changed after the object is created. For example, when you write this code, the compiler actually creates a new string object to hold the new sequence of characters, and that new object is assigned to `b`. The memory allocated for `b` (when it contained the string "h") is then eligible for garbage collection.
5959

6060
```csharp
6161
string b = "h";
@@ -137,6 +137,8 @@ var json= """
137137
""";
138138
```
139139

140+
[!INCLUDE[raw-string-tip](../../includes/raw-string-parsing.md)]
141+
140142
The compiler issues an error if any of the text lines extend to the left of the closing quote sequence. The opening and closing quote sequences can be on the same line, providing the string literal neither starts nor ends with a quote character:
141143

142144
```csharp
@@ -221,12 +223,12 @@ Action<string> stringAction = str => {};
221223
Action<object> objectAction = obj => {};
222224

223225
// Valid due to implicit reference conversion of
224-
// objectAction to Action<string>, but may fail
226+
// objectAction to Action<string>, but might fail
225227
// at run time.
226228
Action<string> combination = stringAction + objectAction;
227229
```
228230

229-
You can create a delegate with the correct runtime type by creating a new delegate object. The following example demonstrates how this workaround may be applied to the preceding example.
231+
You can create a delegate with the correct runtime type by creating a new delegate object. The following example demonstrates how this workaround might be applied to the preceding example.
230232

231233
```csharp
232234
Action<string> stringAction = str => {};

docs/csharp/language-reference/tokens/index.md

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
---
22
description: "Special Characters - C# Reference"
33
title: "Special Characters"
4-
ms.date: 02/14/2017
4+
ms.date: 10/07/2025
55
f1_keywords:
66
- "cs.special characters"
77
- "@$_CSharpKeyword"
@@ -11,7 +11,6 @@ helpviewer_keywords:
1111
- "Visual C#, special characters"
1212
- "@ character (C#)"
1313
- "$ character (C#)"
14-
ms.assetid: 4c5c0539-2e37-40b7-91ce-75af5aabd3f9
1514
---
1615

1716
# C# Special Characters

docs/csharp/language-reference/tokens/interpolated.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
---
22
title: "$ - string interpolation - format string output"
33
description: String interpolation using the `$` token provides a more readable and convenient syntax to format string output than traditional string composite formatting.
4-
ms.date: 11/22/2024
4+
ms.date: 10/07/2025
55
f1_keywords:
66
- "$_CSharpKeyword"
77
- "$"
@@ -60,6 +60,8 @@ To embed `{` and `}` characters in the result string, start an interpolated raw
6060

6161
In the preceding example, an interpolated raw string literal starts with two `$` characters. You need to put every interpolation expression between double braces (`{{` and `}}`). A single brace is embedded into a result string. If you need to embed repeated `{` or `}` characters into a result string, use an appropriately greater number of `$` characters to designate an interpolated raw string literal. If the string literal has more repeated braces than the number of `$` characters, the `{` and `}` characters are grouped from inside to outside. In the preceding example, the literal `The point {{{X}}, {{Y}}}` interprets `{{X}}` and `{{Y}}` as interpolated expressions. The outer `{` and `}` are included verbatim in the output string.
6262

63+
[!INCLUDE[raw-string-tip](../../includes/raw-string-parsing.md)]
64+
6365
## Special characters
6466

6567
To include a brace, "{" or "}", in the text produced by an interpolated string, use two braces, "{{" or "}}". For more information, see the [Escaping braces](../../../standard/base-types/composite-formatting.md#escaping-braces) section of the [Composite formatting](../../../standard/base-types/composite-formatting.md) article.

docs/csharp/language-reference/tokens/raw-string.md

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ description: "Raw string literals can contain any arbitrary text without the nee
33
title: "Raw string literals - \"\"\""
44
f1_keywords:
55
- "RawStringLiteral_CSharpKeyword"
6-
ms.date: 12/08/2022
6+
ms.date: 10/07/2025
77
---
88
# Raw string literal text - `"""` in string literals
99

@@ -21,10 +21,12 @@ The following rules govern the interpretation of a multi-line raw string literal
2121
- Any whitespace to the left of the closing quotes is removed from all lines of the raw string literal.
2222
- Any whitespace following the opening quotes on the same line is ignored.
2323
- Whitespace only lines following the opening quote are included in the string literal.
24-
- If a whitespace precedes the end delimiter on the same line, the exact number and kind of whitespace characters (for example, spaces vs. tabs) must exist at the beginning of each content line. Specifically, a space does not match a horizontal tab, and vice versa.
24+
- If a whitespace precedes the end delimiter on the same line, the exact number and kind of whitespace characters (for example, spaces vs. tabs) must exist at the beginning of each content line. Specifically, a space doesn't match a horizontal tab, and vice versa.
2525
- The newline before the closing quotes isn't included in the literal string.
2626

27-
You may need to create a raw string literal that has three or more consecutive double-quote characters. Raw string literals can start and end with a sequence of at least three double-quote characters. When your string literal contains three consecutive double-quotes, you start and end the raw string literal with four double quote characters:
27+
[!INCLUDE[raw-string-tip](../../includes/raw-string-parsing.md)]
28+
29+
You might need to create a raw string literal that has three or more consecutive double-quote characters. Raw string literals can start and end with a sequence of at least three double-quote characters. When your string literal contains three consecutive double-quotes, you start and end the raw string literal with four double quote characters:
2830

2931
:::code language="csharp" source="./snippets/raw-string-literal.cs" id="MoarQuotes":::
3032

docs/csharp/programming-guide/strings/index.md

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
11
---
22
title: "Strings"
33
description: Learn about strings in C# programming. See information on declaring and initializing strings, the immutability of string objects, and string escape sequences.
4-
ms.date: 11/22/2024
4+
ms.date: 10/07/2025
55
helpviewer_keywords:
66
- "C# language, strings"
77
- "strings [C#]"
8-
ms.assetid: 21580405-cb25-4541-89d5-037846a38b07
98
---
109
# Strings and string literals
1110

@@ -27,11 +26,11 @@ Initialize a string with the <xref:System.String.Empty> constant value to create
2726

2827
## Immutability of strings
2928

30-
String objects are *immutable*: they can't be changed after they're created. All of the <xref:System.String> methods and C# operators that appear to modify a string actually return the results in a new string object. In the following example, when the contents of `s1` and `s2` are concatenated to form a single string, the two original strings are unmodified. The `+=` operator creates a new string that contains the combined contents. That new object is assigned to the variable `s1`, and the original object that was assigned to `s1` is released for garbage collection because no other variable holds a reference to it.
29+
String objects are *immutable*: they can't be changed after they're created. All of the <xref:System.String> methods and C# operators that appear to modify a string actually return the results in a new string object. In the following example, when the contents of `s1` and `s2` are concatenated to form a single string, the two original strings are unmodified. The `+=` operator creates a new string that contains the combined contents. That new object is assigned to the variable `s1`, and the original object assigned to `s1` is released for garbage collection because no other variable holds a reference to it.
3130

3231
:::code language="csharp" source="./snippets/Declarations.cs" id="StringImmutability":::
3332

34-
Because a string "modification" is actually a new string creation, you must use caution when you create references to strings. If you create a reference to a string, and then "modify" the original string, the reference continues to point to the original object instead of the new object that was created when the string was modified. The following code illustrates this behavior:
33+
Because a string "modification" is actually a new string creation, you must use caution when you create references to strings. If you create a reference to a string, and then "modify" the original string, the reference continues to point to the original object. The original object doesn't reflect the new object that was created when the string was modified. The following code illustrates this behavior:
3534

3635
:::code language="csharp" source="./snippets/Declarations.cs" id="ModifyIsCopy":::
3736

@@ -74,6 +73,8 @@ You should consider raw string literals when you're generating text that include
7473

7574
:::code language="csharp" source="./snippets/StringLiterals.cs" id="JSONString":::
7675

76+
[!INCLUDE[raw-string-tip](../../includes/raw-string-parsing.md)]
77+
7778
### String escape sequences
7879

7980
| Escape sequence | Character name | Unicode encoding |
@@ -95,10 +96,10 @@ You should consider raw string literals when you're generating text that include
9596
| `\x` |Unicode escape sequence similar to "\u" except with variable length|`\xH[H][H][H]` (range: 0 - FFFF; example: `\x00E7` or `\x0E7` or `\xE7` = "ç")|
9697

9798
> [!WARNING]
98-
> When using the `\x` escape sequence and specifying less than 4 hex digits, if the characters that immediately follow the escape sequence are valid hex digits (i.e. 0-9, A-F, and a-f), they will be interpreted as being part of the escape sequence. For example, `\xA1` produces "&#161;", which is code point U+00A1. However, if the next character is "A" or "a", then the escape sequence will instead be interpreted as being `\xA1A` and produce "&#x0A1A;", which is code point U+0A1A. In such cases, specifying all 4 hex digits (for example, `\x00A1`) prevents any possible misinterpretation.
99+
> When you use the `\x` escape sequence and specifying less than 4 hex digits, if the characters that immediately follow the escape sequence are valid hex digits (such as 0-9, A-F, and a-f), they're interpreted as being part of the escape sequence. For example, `\xA1` produces "&#161;", which is code point U+00A1. However, if the next character is "A" or "a", then the escape sequence will instead be interpreted as being `\xA1A` and produce "&#x0A1A;", which is code point U+0A1A. In such cases, specifying all 4 hex digits (for example, `\x00A1`) prevents any possible misinterpretation.
99100
100101
> [!NOTE]
101-
> At compile time, verbatim and raw strings are converted to ordinary strings with all the same escape sequences. Therefore, if you view a verbatim or raw string in the debugger watch window, you will see the escape characters that were added by the compiler, not the verbatim or raw version from your source code. For example, the verbatim string `@"C:\files.txt"` will appear in the watch window as `"C:\\files.txt"`.
102+
> At compile time, verbatim and raw strings are converted to ordinary strings with all the same escape sequences. Therefore, if you view a verbatim or raw string in the debugger watch window, you see the escape characters added by the compiler, not the verbatim, or raw version from your source code. For example, the verbatim string `@"C:\files.txt"` appears in the watch window as `"C:\\files.txt"`.
102103
103104
## Format strings
104105

@@ -146,7 +147,7 @@ You can use array notation with an index value to acquire read-only access to in
146147

147148
:::code language="csharp" source="./snippets/StringCharacters.cs" id="ReverseChars":::
148149

149-
If the <xref:System.String> methods don't provide the functionality that you must have to modify individual characters in a string, you can use a <xref:System.Text.StringBuilder> object to modify the individual chars "in-place," and then create a new string to store the results by using the <xref:System.Text.StringBuilder> methods. In the following example, assume that you must modify the original string in a particular way and then store the results for future use:
150+
For more extensive string manipulation, you can use a <xref:System.Text.StringBuilder> object to modify the individual chars "in-place." Then create a new string to store the results by using the <xref:System.Text.StringBuilder> methods. In the following example, assume that you must modify the original string in a particular way and then store the results for future use:
150151

151152
:::code language="csharp" source="./snippets/StringCharacters.cs" id="AccessChars":::
152153

0 commit comments

Comments
 (0)