BRO1405: Statement should not use unnecessary parenthesis¶
Parentheses around a single value, or around a whole expression where nothing binds to it, are removed. Replaces StyleCop SA1119.
Example¶
Before¶
public class Totals
{
private int count = (1 + 2);
public int Sum(int a, int b)
{
var total = (a + b);
return (total);
}
}
After¶
public class Totals
{
private int count = 1 + 2;
public int Sum(int a, int b)
{
var total = a + b;
return total;
}
}
Why¶
Parentheses that don't group anything make the reader look for a precedence question that isn't there.
How the fix works¶
The fix removes ( and ) and any spaces just inside them; where the tokens would run together (return(x)), a
space is left. Before removing, the statement (or member) is parsed again without the parentheses, and they're only
removed when the result means the same: parentheses can turn F(a < b, (c > (d + 1))) into a generic method call
a<b, c>(d + 1) when they go.
Like StyleCop, parentheses inside an operator expression (a + (b * c), a ?? (b ?? c)) are left alone: they say how
the expression groups, or make it clearer. Adding parentheses for clarity is SA1407/SA1408 (the SDK's IDE0048).
In an IDE the parentheses are also faded, like StyleCop's SA1119_p: a hidden companion diagnostic, BRO1405_p, is
reported on the ( and ) of every finding with the Unnecessary tag. It can't be configured, has no fix of its own
(the build and dotnet format ignore hidden diagnostics), and is only reported where BRO1405 is on. Parentheses
around patterns are BRO1410's (with BRO1410_p).
This rule replaces the SDK's IDE0047, whose fix writes merge conflict markers in multi-targeted projects under
dotnet format (reported upstream as dotnet/roslyn#86000) and which also removes a ?? (b ?? c) (see decisions).
Not reported¶
StyleCop's exceptions: operator expressions inside other expressions, a conditional in an interpolation
($"{(f ? 1 : 2)}"), a conditional access before ./[] ((s?.Length).ToString()), a switch or with
expression that is called, cast or accessed, stackalloc in an initializer, the left side of a ref conditional
assignment. Also: parentheses with a comment and a line break inside them (( / x + 1 // one / ): removing them
would leave the ; on a line of its own), and ones whose removal would change how the code parses. A comment on one
line with the code is kept: (x + 1 /* one */) becomes x + 1 /* one */.
Configuration¶
The SDK's dotnet_style_parentheses_* settings don't change this rule: it removes what StyleCop's SA1119 removes. With
never_if_unnecessary the SDK would also remove parentheses inside operator expressions (a ?? (b ?? c)); StyleBro
leaves those, so a StyleCop-clean codebase stays unchanged after migrating. never_if_unnecessary does turn off adding
parentheses (BRO1406, BRO1407).
Compared with StyleCop¶
Same positions, except the parse-changing case above, where StyleCop's fix doesn't compile. StyleCop's fix leaves the
spaces of ( b ) behind.
StyleCop also reports a hidden SA1119_p on the same parentheses' ( and ), only so the IDE greys them out; StyleBro
does the same with BRO1405_p (see above). StyleCop doesn't check parentheses in patterns (x is (> 0)); StyleBro's
BRO1410 does.