Analyzer
SF0001
Flags interfaces that introduce indirection without delivering polymorphism because the solution only has one concrete implementation.
Diagnostic contract
An interface with one implementation is usually ceremony. It makes navigation, DI setup, and onboarding harder without buying substitution power.
Exactly one non-abstract class or struct implements the interface in source.
Interface {0} has exactly one non-abstract implementation: {1}. Remove the interface and use the concrete type directly.
/analyzers/sf0001/
When it fires
These are the concrete cases to look for in code review and IDE diagnostics.
- The analyzer looks only at source-defined interfaces, then finds concrete classes or structs that implement them.
- It reports only when there is exactly one non-abstract implementation. Zero or multiple implementations are left alone.
- The rule belongs to the HalfRule category because it measures speculative abstraction.
Bad / better example
Use these examples to explain the rule, not just silence it.
Before
public interface IPricingService
{
decimal Calculate(Order order);
}
public sealed class DefaultPricingService : IPricingService
{
public decimal Calculate(Order order) => order.Total * 0.95m;
}
public sealed class CheckoutHandler(IPricingService pricingService)
{
public decimal Quote(Order order) => pricingService.Calculate(order);
} The interface exists, but the codebase only ever uses DefaultPricingService.
After
public sealed class DefaultPricingService
{
public decimal Calculate(Order order) => order.Total * 0.95m;
}
public sealed class CheckoutHandler(DefaultPricingService pricingService)
{
public decimal Quote(Order order) => pricingService.Calculate(order);
} The direct dependency makes the real shape obvious and removes one layer of indirection.
Code fix
The code fix rewrites interface references to the concrete implementation, removes the interface declaration, and preserves dependent interface members where possible.
- Use the lightbulb in the IDE when the interface exists only as ceremony.
- Review the result if the interface participates in a larger hierarchy; the fixer preserves direct dependent members but cannot invent missing abstraction value.
- This is one of the two diagnostics with an in-repo code fix today.
Source and follow-up links
Use these links when you need to validate behavior against the source or connect the docs back to project tracking.
Analyzer implementation
SingleImplementationInterfaceAnalyzer.cs
Code fixImplementation details
SingleImplementationInterfaceCodeFixProvider.cs
TrackingIssue #55
Documentation tracker for the analyzer pages and related integration guidance.
GuideAnalyzer install guide
See the correct PackageReference shape for enabling the rule in another solution.
FilterHalfRule
This diagnostic is a concrete way the HalfRule surfaces speculative abstraction.