prefer_switch_expression
This rule flags a switch statement whose every case is a single statement and where all of them do the same kind of thing: return a value, or assign to the same variable.
That switch is producing a value while pretending to be control flow. A switch expression says so, drops the case/return scaffolding, and — because it is an expression — the compiler checks exhaustiveness at the point the value is needed. The quick fix does the conversion.
See also: Switch expressions
Every case returns:
enum DeliveryStage { packed, shipped, delivered }
enum DeliveryIcon { box, truck, home }
DeliveryIcon iconFor(DeliveryStage stage) { switch (stage) { case DeliveryStage.packed: return DeliveryIcon.box; case DeliveryStage.shipped: return DeliveryIcon.truck; case DeliveryStage.delivered: return DeliveryIcon.home; }}Every case assigns the same variable, which then has to be declared uninitialised above:
enum DeliveryIcon { box, truck, home }
String describe(DeliveryIcon icon) { String description; switch (icon) { case DeliveryIcon.box: description = 'Waiting in the warehouse'; case DeliveryIcon.truck: description = 'On the road'; case DeliveryIcon.home: description = 'Dropped at the door'; } return description;}enum DeliveryStage { packed, shipped, delivered }
enum DeliveryIcon { box, truck, home }
DeliveryIcon iconFor(DeliveryStage stage) => switch (stage) { DeliveryStage.packed => DeliveryIcon.box, DeliveryStage.shipped => DeliveryIcon.truck, DeliveryStage.delivered => DeliveryIcon.home,};The assigning form collapses into a final, so the variable is never in an unassigned state:
enum DeliveryIcon { box, truck, home }
String describe(DeliveryIcon icon) { final description = switch (icon) { DeliveryIcon.box => 'Waiting in the warehouse', DeliveryIcon.truck => 'On the road', DeliveryIcon.home => 'Dropped at the door', }; return description;}A default becomes the wildcard _:
String name(int value) => switch (value) { 1 => 'one', 2 => 'two', _ => 'unknown',};Known limitations
Section titled “Known limitations”Anything that is not a clean value-producing switch is left alone, because the rewrite would not be exact:
- A case with more than one statement.
- A case that falls through (empty body) — unless
allow_fallthrough_casesis on, see below. - Mixed cases: some returning, some assigning.
- Cases assigning to different variables.
Turning this rule off
Section titled “Turning this rule off”This rule is in the opinionated preset, so it is on with
preset: opinionated, or by name:
rules: prefer_switch_expression: trueTo turn it off again:
rules: prefer_switch_expression: falseTo keep the rule on but skip certain paths, use per-rule exclude.
Options
Section titled “Options”allow_fallthrough_cases
Section titled “allow_fallthrough_cases”Off by default. Turn it on to also report a switch where several cases share
one body — the quick fix merges their patterns with ||:
many_lints: rules: prefer_switch_expression: allow_fallthrough_cases: truerules: prefer_switch_expression: allow_fallthrough_cases: trueenum DeliveryStage { packed, shipped, delivered }
// Don'tbool isMoving(DeliveryStage stage) { switch (stage) { case DeliveryStage.packed: case DeliveryStage.shipped: return true; case DeliveryStage.delivered: return false; }}
// Dobool isMovingExpression(DeliveryStage stage) => switch (stage) { DeliveryStage.packed || DeliveryStage.shipped => true, DeliveryStage.delivered => false,};A trailing fallthrough — an empty last case with nothing after it to share a body with — has no pattern to merge into and stays unreported even with the option on.
| Option | Type | Default | Description |
|---|---|---|---|
allow_fallthrough_cases |
bool | false |
Also report switches where cases share a body. The quick fix merges them into a single case a || b pattern; a trailing fallthrough has nothing to merge into and stays unreported |
Related rules
Section titled “Related rules”avoid_nested_conditional_expressions— Flag a conditional nested inside another.prefer_conditional_expressions— Collapse a two-way if/else into a conditional expression.prefer_switch_with_enums— Use a switch instead of an if-else chain over enum constants.no_equal_switch_case— Flag two switch branches with identical bodies.