C# Language Support in ReSharper and Rider 2025.1
Our release for ReSharper and Rider 2025.1 is just around the corner, and we have lots of exciting features shipping for the current and next version of C#! This will be a really long post (blame our awesome devs!), so make sure to use the table of contents on the right. Oh, and of course… […]

Our release for ReSharper and Rider 2025.1 is just around the corner, and we have lots of exciting features shipping for the current and next version of C#! This will be a really long post (blame our awesome devs!), so make sure to use the table of contents on the right. Oh, and of course…
For many of the inspections and quick fixes discussed in this post, we recommend using either find in scope or fix in scope to effectively use them in your codebases. Now, let’s talk about new features!
Structured Logging Support
In ReSharper and Rider 2025.1, we enhanced support for structured and high-performance logging using the Microsoft.Extensions.Logging
APIs. Similar to how formatting arguments are highlighted in string.Format
using the {0}
syntax, we now highlight the corresponding type arguments in the Logger.Define
and LoggerMessageAttribute
API. Additionally, missing type arguments are now reported with diagnostics to catch issues early, along with quick-fixes and context actions to add or remove them as needed:
String Construction Context Actions
Our .NET IDEs offer a wide range of suggestions and context actions for working with C# string literals, interpolated strings, string.Format
, and StringBuilder
constructs. You can convert nearly any string-related expression into various other forms to enhance readability or to better parameterize string construction.
However, some conversion directions were still missing. For example, while it’s been easy to convert a concatenated string like "Id = " + someId
into either an interpolated string $"Id = {someId}"
or a format string string.Format("Id = {0}", someId)
, there hasn’t been a way to reverse this — i.e., to convert interpolated or formatted strings back into concatenation. In certain scenarios, such a transformation can actually result in more concise or readable code:
Improved Multiline To-Do Comments
In the previous release, we introduced support for multiline to-do comments, where subsequent lines were considered part of the same item based on their indentation. In the 2025.1 release, we’ve enhanced this feature by making indentation optional. Now, lines following a to-do comment are automatically treated as part of the same item, even without indentation, making multiline comments more intuitive and seamless. However, if indentation is used, it will be strictly enforced:
Language Injection in Return Values
Language injection made its debut in ReSharper around 10 years ago with support for regular expressions. Since then, it has been brought to Rider, expanded to other languages, and updated to work with new language and runtime features.
Previously, the LanguageInjection
attribute (from JetBrains.Annotations
) could only be applied to parameters, fields, and properties. Now you can annotate methods to specify that their returned strings represent an embedded code of another language:
Redundant Duplicated Code
In the previous two versions, we introduced inspections for more specific scenarios of code duplication — common code in if
and switch
statements and duplicated switch
section bodies. In this 2025.1 release, we deliver three new inspections to help you eliminate unintentional duplications and improve readability and maintainability in your codebase.
Our first inspection detects duplicated statements that appear both within conditional branches of if
and switch
statements ending with jump statements and again immediately afterward:
Another inspection detects redundant arms in switch expressions — specifically, arms that return the same value as the default one. Removing these redundancies simplifies your code and improves readability:
The last inspection detects when multiple if
branches execute identical code and provides a handy quick-fix to merge them:
Misuse of CancellationToken
When working with asynchronous methods, it’s common to pass a CancellationToken
through parameters of local functions or lambda expressions. Accidentally using a method-level token instead of a more specific, locally scoped one can lead to unintended behavior, such as tasks not being canceled when expected.
ReSharper and Rider 2025.1 introduce a new inspection that detects when a broader-scoped cancellation token is mistakenly used instead of a more appropriate local token available within a local function or lambda. You can choose from two corresponding quick-fixes to either a) replace the mistakenly used token with the correct local token, or b) link both tokens into one using CancellationTokenSource.CreateLinkedTokenSource
:
Injection Postfix Template
Primary constructors in C# 12 greatly simplify constructor dependency injection patterns. You only need to mention a dependency once in the constructor parameter list, and it automatically becomes available across all instance members of the class without the need to define and assign a field explicitly.
In ReSharper and Rider 2025.1, we introduce a new inject
postfix template available for type names. When you realize you need to add a dependency on IService
, select it from the completion list, append .inject
, and hit your completion key:
Transform Parameters Refactoring
The transform parameters refactoring makes it easy to change a method’s signature by modifying its parameters — for example, removing out
parameters, wrapping them in a tuple or a new class, and more — while automatically updating all usages of the method across your solution.
With ReSharper and Rider 2025.1, we reworked the refactoring to support modern language features (including tuple types, record classes, and primary constructors), treat tuple elements as multiple return values, transform ref
parameters into both input and output values, and handle lots of deconstruction usages. Bring up the dialog, select the parameters you want to transform, and choose your desired target types:
Context Highlighters for Extended Types
One of the very subtle features in ReSharper and Rider is the highlighting of matching code elements (for instance, check out Matching of control flow keywords). From 2025.1, we will help you to visually identify members that extend the base class or implement some concrete interface type. Just place the caret over the type name in the base types clause:
Chop Formatting Context Action
Our built-in formatter helps you to align your code with your preferred code formatting style settings. It can be invoked manually, through an “on-save” action, or before committing changes. Sometimes, though, you may want more control without triggering widespread formatting. A new context action lets you apply chop formatting to various C# constructs directly without needing to make a selection:
Modification in Debug.Assert
When writing code assertions using APIs like Debug.Assert
, it’s easy to forget that these calls are stripped out in RELEASE
builds. This is because methods marked with attributes like [Conditional("DEBUG")]
are only compiled when the DEBUG
symbol is defined in the project. As a result, if the assertion condition includes side effects — such as assignments or collection mutations — those side effects will not occur in RELEASE
builds. These conditional side effects are hard to spot and reason about, and they can lead to subtle bugs or unexpected behavior.
Our new 2025.1 code inspection detects and warns you about such cases automatically:
Inexact Stream Reads
A common mistake when working with .NET’s Stream
class is misusing the Read
and ReadAsync
methods. These methods accept a buffer (an array or a Span
) and are often assumed to fill it completely — but they are not guaranteed to do so. Crucially, Stream
implementations are allowed to return partial data and will report the actual number of bytes read, which may be less than the buffer size. That’s why it’s essential to handle the return value from Read
and ReadAsync
properly and continue reading until the desired amount of data is received.
Starting with our 2025.1 IDEs, incorrect usage patterns of Read
and ReadAsync
are automatically detected, with suggestions to replace them with the safer ReadExactly
API:
Tuple Component Names
Tuple types allow you to use both explicit and generic component names. Sometimes, it is overlooked that a component can be referenced by its explicit name, e.g., MyComponent
, rather than ItemN
. Our new IDE hint and corresponding quick-fix help you to get rid of generic names in favor of explicit names to make your code more readable:
Referencing Enum Member Names
The nameof
operator was introduced in C# 6 — another case of “10 years today”! Since then, many have embraced it extensively to reference variable, type, and member names as string constants instead of using magic strings. ReSharper and Rider continue to spot situations [1, 2] in which you can make better use of them. Referencing an enum member through ToString
introduces unnecessary runtime overhead due to reflection and additional processing.
In 2025.1, we are adding a new inspection Use nameof
expression to reference enum member name that targets such cases and provides a quick-fix to convert to nameof
as a compile-time language feature that is faster, safer, and clearer:
Nameof with Unbound Generics
Another new feature in C# 14 now allows using the nameof
operator with unbound generics. Previously, to get List
as a compile-time constant, you had to provide generic arguments — e.g., nameof(List
— even though they are not included in the final name. This friction is now removed, and you can use the open generic as in nameof(List<>)
.
ReSharper and Rider identify places where generic types in nameof
operators can be simplified and provide a quick-fix to remove redundancies:
First-Class Span Types
In recent years, the BCL and many other libraries have extensively adopted Span
and ReadOnlySpan
to provide more performant APIs. With C# 14, first-class support for span types is introduced through new implicit conversions between ReadOnlySpan
, Span
, and T[]
, which are now applied in more scenarios. This makes working with spans more intuitive and seamless. ReSharper and Rider 2025.1 fully support these updated conversion rules:
Simple Lambda Parameters with Modifiers
The next C# update simplifies writing lambda signatures. Previously, using parameter modifiers like ref
, out
, in
, ref readonly
, or scoped
in lambdas required explicitly specifying the parameter type — for no particular reason. Starting with C# 14, this restriction has been lifted, allowing you to use these modifiers without redundant type annotations.
As you’d expect, ReSharper and Rider 2025.1 offer a quick-fix to remove the now-redundant type specifications:
Default Literal Suggestions
C# is well-known for offering multiple ways to express the same concept (looking at you, null checks!). While flexibility has its merits, this kind of redundancy is generally not a good thing. It’s exactly why IDE tooling plays a crucial role in helping developers standardize and streamline code — ensuring consistency and reducing ambiguity.
Using the default
literal in non-generic contexts to represent trivial values like 0
or false
can make code harder to reason about. ReSharper and Rider now help you catch such cases and offer recommendations to clarify the intent:
Conclusion
Wow — that was a lot to cover! One thing’s clear: our team has poured serious effort into not just flashy new language features but also refining older ones, making them shine in fresh ways.
We’d love to hear from you. Do you spot any issues or have ideas for ReSharper and Rider vNextNext
? Drop them in the comments!