Missing Switch Default
ID |
csharp.missing_switch_default |
Severity |
high |
Remediation Complexity |
trivial |
Remediation Risk |
low |
Remediation Effort |
low |
Resource |
Reliability |
Language |
CSharp |
Tags |
control-flow, reliability, switch |
Description
Reports switch statements that declare no default section. A switch over an enum is reported
too, even when every member declared today has a case label. Only switch expressions
(x switch { … }) are exempt.
Rationale
A switch without a default section does nothing at all for every value the author did not
enumerate. A new protocol code, an unexpected status string or a value that slipped past input
validation then flows on silently with the state it had before the switch, and the defect
surfaces far from its cause. An explicit default forces a decision: fall back to a documented
behaviour, or fail loudly.
This holds for an enum selector too. Covering every member that exists today proves nothing about tomorrow — an enum is extended by adding a member, and a switch that enumerated the old set stops handling the new one without a single compiler warning.
public string Describe(int code)
{
switch (code) // FLAW — nothing happens for any other code
{
case 1:
return "created";
case 2:
return "deleted";
}
return null;
}
public string Name(Level level)
{
switch (level) // FLAW — Level may gain a member later
{
case Level.Low:
return "low";
case Level.High:
return "high";
}
return null;
}
public string DescribeSafely(int code)
{
switch (code) // OK — the fallback is explicit
{
case 1:
return "created";
case 2:
return "deleted";
default:
throw new ArgumentOutOfRangeException(nameof(code));
}
}
Remediation
Add a default section. Prefer a fallback that cannot be mistaken for success: throw
ArgumentOutOfRangeException, log the unexpected value, or return a well-defined "unknown"
result. If the enumeration really is complete and a fallback is meaningless, convert the
statement into a switch expression so the compiler checks exhaustiveness for you.