diff --git a/.github/prompts/error-consolidation.md b/.github/prompts/error-consolidation.md index b0e0fab4bd71d..314667b3eef78 100644 --- a/.github/prompts/error-consolidation.md +++ b/.github/prompts/error-consolidation.md @@ -12,8 +12,8 @@ Overall steps: We're going to work through a series of files consolidating errors and warnings. -- For the duration of this chat, all references to "destination file" refer to `pattern-matching-warnings.md`. -- For the duration of this chat, all references to "the target theme" refer to errors and warnings related to list patterns, and other pattern matching features. +- For the duration of this chat, all references to "destination file" refer to `string-interpolations.md`. +- For the duration of this chat, all references to "the target theme" refer to errors and warnings related to string interpolations, and string interpolation handlers. The destination file already contains a skeleton for the final output. diff --git a/docs/csharp/language-reference/compiler-messages/ref-modifiers-errors.md b/docs/csharp/language-reference/compiler-messages/ref-modifiers-errors.md index 30daf67e4d644..3d16f7366fa28 100644 --- a/docs/csharp/language-reference/compiler-messages/ref-modifiers-errors.md +++ b/docs/csharp/language-reference/compiler-messages/ref-modifiers-errors.md @@ -55,7 +55,6 @@ f1_keywords: - "CS9199" - "CS9200" - "CS9201" - - "CS9205" - "CS9265" helpviewer_keywords: - "CS0192" @@ -111,7 +110,6 @@ helpviewer_keywords: - "CS9199" - "CS9200" - "CS9201" - - "CS9205" - "CS9265" ai-usage: ai-assisted ms.date: 11/21/2025 @@ -179,7 +177,6 @@ The following warnings are generated when reference variables are used incorrect - [**CS9198**](#reference-variable-restrictions): *Reference kind modifier of parameter doesn't match the corresponding parameter in target.* - [**CS9200**](#reference-variable-restrictions): *A default value is specified for `ref readonly` parameter, but `ref readonly` should be used only for references. Consider declaring the parameter as `in`.* - [**CS9201**](#reference-variable-restrictions): *Ref field should be ref-assigned before use.* -- [**CS9205**](#incorrect-syntax): *Expected interpolated string.* - [**CS9265**](#reference-variable-restrictions): *Field is never ref-assigned to, and will always have its default value (null reference)* These errors and warnings follow these themes: @@ -198,15 +195,12 @@ These errors indicate that you're using incorrect syntax regarding reference var - **CS8373**: *The left-hand side of a `ref` assignment must be a ref variable.* - **CS8388**: *An `out` variable cannot be declared as a ref local.* - **CS9190**: *`readonly` modifier must be specified after `ref`.* -- **CS9205**: *Expected interpolated string.* To correct these errors: - Ensure the left operand of a `= ref` operator is a reference variable rather than a value expression or non-reference local. Ref assignment requires both sides to be reference variables that can create an alias to the same storage location (**CS8373**). - When declaring reference parameters, write the modifier as `ref readonly` rather than `readonly ref`. The C# language specification requires the `ref` keyword to precede the `readonly` modifier in parameter declarations to maintain consistent syntax across all reference parameter types (**CS9190**). - Use the `ref` keyword instead of `out` when declaring local reference variables. `out` is exclusively a parameter modifier that indicates a method must assign a value before returning, whereas `ref` is the appropriate keyword for creating local variables that alias other storage locations (**CS8388**). -- Pass a regular variable or value expression instead of an interpolated string when calling a method with an `out` parameter. Interpolated strings are immutable temporary values that can't be used as output parameters since they don't represent assignable storage locations (**CS9205**). - For more information about reference variables and their syntax requirements, see [reference variables](../statements/declarations.md#reference-variables) and the [C# Language Specification](~/_csharpstandard/standard/variables.md#97-reference-variables-and-returns). ## Reference variable restrictions diff --git a/docs/csharp/language-reference/compiler-messages/string-interpolations.md b/docs/csharp/language-reference/compiler-messages/string-interpolations.md new file mode 100644 index 0000000000000..5d52334aea711 --- /dev/null +++ b/docs/csharp/language-reference/compiler-messages/string-interpolations.md @@ -0,0 +1,78 @@ +--- +title: Resolve errors and warnings for string interpolation expressions +description: Learn how to diagnose and correct C# compiler errors and warnings when you use string interpolation expressions, where expressions are substituted for placeholders in a string literal. +f1_keywords: + - "CS8361" + - "CS8941" + - "CS8942" + - "CS8946" + - "CS8947" + - "CS8953" + - "CS8976" + - "CS9205" + - "CS9325" +helpviewer_keywords: + - "CS8361" + - "CS8941" + - "CS8942" + - "CS8946" + - "CS8947" + - "CS8953" + - "CS8976" + - "CS9205" + - "CS9325" +ms.date: 02/06/2026 +ai-usage: ai-assisted +--- +# Resolve errors and warnings for string interpolation expressions + +The C# compiler generates errors and warnings when you declare string interpolation expressions or string interpolation handlers with incorrect syntax or use them in unsupported contexts. These diagnostics help you identify problems with string interpolations or custom string interpolation handlers. + + +- [**CS8361**](#interpolation-expression-syntax): *A conditional expression cannot be used directly in a string interpolation because the ':' ends the interpolation. Parenthesize the conditional expression.* +- [**CS8941**](#interpolated-string-handler-type-implementation): *Interpolated string handler method is malformed. It does not return 'void' or 'bool'.* +- [**CS8942**](#interpolated-string-handler-type-implementation): *Interpolated string handler method has inconsistent return type. Expected to return a different type.* +- [**CS8946**](#interpolated-string-handler-type-implementation): *Type is not an interpolated string handler type.* +- [**CS8947**](#interpolated-string-handler-usage-restrictions): *Parameter occurs after interpolated string handler parameter in the parameter list, but is used as an argument for interpolated string handler conversions. This will require the caller to reorder parameters with named arguments at the call site. Consider putting the interpolated string handler parameter after all arguments involved.* +- [**CS8953**](#interpolated-string-handler-usage-restrictions): *An interpolated string handler construction cannot use dynamic. Manually construct an instance instead.* +- [**CS8976**](#interpolated-string-handler-usage-restrictions): *Interpolated string handler conversions that reference the instance being indexed cannot be used in indexer member initializers.* +- [**CS9205**](#interpolation-expression-syntax): *Expected interpolated string.* +- [**CS9325**](#interpolated-string-handler-usage-restrictions): *Interpolated string handler arguments are not allowed in this context.* + +## Interpolation expression syntax + +- **CS8361** - *A conditional expression cannot be used directly in a string interpolation because the ':' ends the interpolation. Parenthesize the conditional expression.* +- **CS9205** - *Expected interpolated string.* + +To correct these errors, apply the following techniques: + +- Wrap conditional expressions (ternary `?:` operator) in parentheses when you use them inside an interpolation hole (**CS8361**). The colon character has special meaning in [interpolated strings](../tokens/interpolated.md) as it introduces a format string, so the compiler interprets the `:` in `condition ? true : false` as a format specifier rather than part of the conditional expression. For example, use `$"{(x > 0 ? "positive" : "negative")}"` instead of `$"{x > 0 ? "positive" : "negative"}"`. +- Ensure you provide an interpolated string literal where one is expected (**CS9205**). This error occurs when the compiler expects an interpolated string (beginning with `$"` or `$@"`) but encounters a different expression type. + +## Interpolated string handler type implementation + +- **CS8941** - *Interpolated string handler method is malformed. It does not return 'void' or 'bool'.* +- **CS8942** - *Interpolated string handler method has inconsistent return type. Expected to return a different type.* +- **CS8946** - *Type is not an interpolated string handler type.* + +When you implement a custom [interpolated string handler](../../advanced-topics/performance/interpolated-string-handler.md), apply the following techniques: + +- Make sure all `AppendLiteral` and `AppendFormatted` methods return either `void` or `bool` (**CS8941**). The handler pattern requires these methods to have one of these return types so the compiler can properly generate the interpolation code. Methods returning `bool` enable short-circuiting when the handler determines that further processing isn't needed. +- Make sure all append methods in your handler type use the same return type (**CS8942**). If one method returns `void`, all append methods must return `void`. If one returns `bool`, all must return `bool`. Mixing return types prevents the compiler from generating consistent interpolation code. +- Apply the to your handler type and make sure it has a valid constructor (**CS8946**). An interpolated string handler type must be marked with this attribute and follow the [handler pattern](~/_csharplang/proposals/csharp-10.0/improved-interpolated-strings.md#the-handler-pattern) to be recognized by the compiler. + +## Interpolated string handler usage restrictions + +- **CS8947** - *Parameter occurs after the interpolated string handler parameter in the parameter list, but is used as an argument for interpolated string handler conversions. This will require the caller to reorder parameters with named arguments at the call site. Consider putting the interpolated string handler parameter after all arguments involved.* +- **CS8953** - *An interpolated string handler construction cannot use dynamic. Manually construct an instance of '{0}'.* +- **CS8976** - *Interpolated string handler conversions that reference the instance being indexed cannot be used in indexer member initializers.* +- **CS9325** - *Interpolated string handler arguments are not allowed in this context.* + +When you use interpolated string handlers, apply the following techniques: + +- Reorder method parameters so that any parameters used by the appear before the interpolated string handler parameter (**CS8947**). This warning indicates that callers would need to use named arguments to properly invoke the method, which reduces usability. Place the handler parameter after all arguments it depends on. +- Don't use `dynamic` typed values as arguments to interpolated string handler conversions (**CS8953**). The compiler can't determine the handler's construction requirements at compile time when dynamic values are involved. Instead, manually construct the handler instance and call its methods directly. +- Don't use interpolated strings that reference the instance being initialized in indexer member initializers (**CS8976**). During object initialization, the instance isn't fully constructed, so handler conversions that reference it through `this` aren't allowed. Use a separate statement after initialization to set the indexer value. +- Check the context where you're using interpolated string handler arguments (**CS9325**). Some contexts don't support handler argument attributes. In these cases, use a regular interpolated string or manually construct the handler. diff --git a/docs/csharp/language-reference/toc.yml b/docs/csharp/language-reference/toc.yml index c62c7a2ae55cf..9777c43856cf1 100644 --- a/docs/csharp/language-reference/toc.yml +++ b/docs/csharp/language-reference/toc.yml @@ -547,7 +547,7 @@ items: CS8329, CS8330, CS8331, CS8332, CS8337, CS8338, CS8373, CS8388, CS8977, CS8986, CS8987, CS9061, CS9062, CS9063, CS9065, CS9066, CS9072, CS9073, CS9074, CS9101, CS9102, CS9104, CS9190, CS9191, CS9192, CS9193, CS9195, CS9196, CS9197, CS9198, - CS9199, CS9200, CS9201, CS9205, CS9265 + CS9199, CS9200, CS9201, CS9265 - name: Ref safety href: ./compiler-messages/ref-safety-errors.md displayName: > @@ -609,6 +609,10 @@ items: CS1009, CS1010, CS1011, CS1012, CS1039, CS8996, CS8997, CS8998, CS8999, CS9000, CS9001, CS9002, CS9003, CS9004, CS9005, CS9006, CS9007, CS9008, CS9009, CS9026, CS9047, CS9274, CS9315 + - name: String interpolations + href: ./compiler-messages/string-interpolations.md + displayName: > + CS8361, CS8941, CS8942, CS8946, CS8947, CS8953, CS8976, CS9205, CS9325 - name: Array declarations href: ./compiler-messages/array-declaration-errors.md displayName: > diff --git a/docs/csharp/misc/sorry-we-don-t-have-specifics-on-this-csharp-error.md b/docs/csharp/misc/sorry-we-don-t-have-specifics-on-this-csharp-error.md index 4f00471374be6..01d3609a06a44 100644 --- a/docs/csharp/misc/sorry-we-don-t-have-specifics-on-this-csharp-error.md +++ b/docs/csharp/misc/sorry-we-don-t-have-specifics-on-this-csharp-error.md @@ -269,7 +269,6 @@ f1_keywords: - "CS8357" - "CS8359" - "CS8360" - - "CS8361" - "CS8362" - "CS8372" - "CS8375" @@ -428,11 +427,6 @@ f1_keywords: - "CS8935" - "CS8937" - "CS8940" - - "CS8941" - - "CS8942" - - "CS8946" - - "CS8947" - - "CS8953" - "CS8954" - "CS8955" - "CS8956" @@ -445,7 +439,6 @@ f1_keywords: - "CS8970" - "CS8973" - "CS8974" - - "CS8976" # Coming in C# 15 - "CS9343" - "CS9344"