Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/prompts/error-consolidation.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,6 @@ f1_keywords:
- "CS9199"
- "CS9200"
- "CS9201"
- "CS9205"
- "CS9265"
helpviewer_keywords:
- "CS0192"
Expand Down Expand Up @@ -111,7 +110,6 @@ helpviewer_keywords:
- "CS9199"
- "CS9200"
- "CS9201"
- "CS9205"
- "CS9265"
ai-usage: ai-assisted
ms.date: 11/21/2025
Expand Down Expand Up @@ -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:
Expand All @@ -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
Expand Down
Original file line number Diff line number Diff line change
@@ -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.

<!-- The text in this list generates issues for Acrolinx, because they don't use contractions.
That's by design. The text closely matches the text of the compiler error / warning for SEO purposes.
-->
- [**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 <xref:System.Runtime.CompilerServices.InterpolatedStringHandlerAttribute> 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 <xref:System.Runtime.CompilerServices.InterpolatedStringHandlerArgumentAttribute> 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.
6 changes: 5 additions & 1 deletion docs/csharp/language-reference/toc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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: >
Expand Down Expand Up @@ -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: >
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -269,7 +269,6 @@ f1_keywords:
- "CS8357"
- "CS8359"
- "CS8360"
- "CS8361"
- "CS8362"
- "CS8372"
- "CS8375"
Expand Down Expand Up @@ -428,11 +427,6 @@ f1_keywords:
- "CS8935"
- "CS8937"
- "CS8940"
- "CS8941"
- "CS8942"
- "CS8946"
- "CS8947"
- "CS8953"
- "CS8954"
- "CS8955"
- "CS8956"
Expand All @@ -445,7 +439,6 @@ f1_keywords:
- "CS8970"
- "CS8973"
- "CS8974"
- "CS8976"
# Coming in C# 15
- "CS9343"
- "CS9344"
Expand Down