Redundant Modifiers

ID

csharp.redundant_modifiers

Severity

low

Remediation Complexity

medium

Remediation Risk

low

Remediation Effort

medium

Resource

Code Smell

Language

CSharp

Tags

code-style, redundancy

Description

Reports declarations whose modifiers cannot have any effect in the surrounding context. The first version of the rule focuses on the virtual modifier applied to a member of a sealed class.

Rationale

A sealed class cannot be inherited from, so any virtual member declared in it can never be overridden. The virtual keyword therefore adds no behaviour, only noise; worse, it advertises an extensibility point that the surrounding class explicitly forbids, which misleads readers about the type’s design intent. The modifier should be removed to make the contract honest.

public sealed class Calculator
{
    public virtual int Add(int a, int b) => a + b;   // FLAW
    public virtual string Name => "calc";             // FLAW

    public int Sub(int a, int b) => a - b;            // OK
}

public class Base                                     // OK, can be inherited
{
    public virtual int Add(int a, int b) => a + b;
}

Remediation

Drop the redundant modifier. If the type was meant to support overrides, remove the sealed keyword from the class declaration instead.