[Visual Studio] [C# 14] Private extension methods incorrectly marked as unused members
This issue has been moved from a ticket on Developer Community.
[severity:It bothers me. A fix would be nice] When using the new C# 14 extension method syntax, Visual Studio 18.0.2 marks private extension methods as "unused members" but only if it is not called using the extension method signature. Surely this is the side-effect of some compiler lowering to old-style extension syntax, but the IDE suggestion is just wrong and would lead to a compiler error.
Example:
public static class NewStyleExtensions
{
extension(string input)
{
public T[] SplitToArray<T>(char separator) where T : IConvertible
=> [.. input.Split(separator).Select(ConvertTo<T>)];
private T ConvertTo<T>() where T : IConvertible // <--- This method gets wrongfully marked as "unused member"
=> (T)Convert.ChangeType(input, typeof(T));
}
}
Note that changing the call from the public method affects this behavior:
// Alternative 1
// When called with the true extension method signature, the private method is now correctly marked as "used".
public T[] SplitToArray<T>(char separator) where T : IConvertible
=> [.. input.Split(separator).Select(x => x.ConvertTo<T>())];
// Alternative 2
// When called with the target as an input parameter, the private method is incorrectly marked as "unused" and a refactor is suggested to remove the lambda expression (to original example above).
public T[] SplitToArray<T>(char separator) where T : IConvertible
=> [.. input.Split(separator).Select(x => ConvertTo<T>(x))];
Original Comments
Benjamin Copass on 12/11/2025, 01:27 AM:
Another example / use case:
internal static class PrivateExtensionPropertyTest
{
extension(object o)
{
private bool Foo => o is null; // faded out in Visual Studio (VS thinks it's an unused member)
}
public static void Test()
{
object o = new object();
bool b = o.Foo; // Foo is actually used
}
}
Feedback Bot on 12/11/2025, 06:50 AM:
We have directed your feedback to the appropriate engineering team for further evaluation. The team will review the feedback and notify you about the next steps.
Related to https://github.com/dotnet/roslyn/issues/80645
Moved to Area-IDE as this seems driven by IDE0051 Also relates to https://github.com/dotnet/roslyn/issues/81213
I'm not sure if this is handled by the same IDE logic, but extension members and their implementation methods are also not tracked together in FAR and other refactorings: https://github.com/dotnet/roslyn/issues/81507
Closing as duplicate of https://github.com/dotnet/roslyn/issues/80645 I'm working on a fix for 18.3