BRO1509: An element should not be on a single line¶
Types, namespaces, method bodies (including constructors, operators and local functions) and accessor lists with bodies put their braces and contents on separate lines. Replaces StyleCop SA1502.
Example¶
Before¶
namespace Shop
{
public class Empty { }
public class Price { private decimal amount; public decimal Amount { get { return this.amount; } } public void Clear() { this.amount = 0; } }
}
After¶
namespace Shop
{
public class Empty
{
}
public class Price
{
private decimal amount;
public decimal Amount
{
get { return this.amount; }
}
public void Clear()
{
this.amount = 0;
}
}
}
Why¶
Declarations that always look the same are easy to scan, and a member written on one line has to be reformatted as soon as it grows.
How the fix works¶
The braces get their own lines at the declaration's indentation and each member, statement or accessor inside goes on
its own line one level deeper (from indent_style/indent_size in .editorconfig). Members that
BRO1505 wants separated get their blank line right away, and a statement in a method body that
BRO1514-BRO1516 want braces on gets them (void M(bool x) { if (x) return; }), so one
dotnet format run is enough. That includes a property whose one-line accessor list is expanded: it spans several lines
then, so it's separated from a neighbouring property by a blank line (two one-line properties may sit together). A statement after a local function's } gets BRO1519's blank line. Enum values
each get their own line with a trailing comma (none with stylebro_trailing_comma = omit), which BRO1121 and BRO1401 want (StyleCop's fix
keeps them on one line, which its own SA1136 then reports); accessors stay on one line each
(get { return this.amount; }), which StyleCop allows. With csharp_new_line_before_open_brace not including the
element's kind (types, methods, local_functions, properties, indexers, events), the { stays at the end of
the declaration's line. With csharp_preserve_single_line_statements = false a statement without braces (if (x) y;, loops, else) gets its embedded statement on its own line, one level deeper, as the SDK's whitespace formatting would do once the block isn't on one line (it runs before the fixes, so otherwise a second run). Nested ones (for (...) if (x) y;) go one level deeper each, a using right inside a using stays at its level, and a one-line switch gets the formatter's layout: labels and statements on their own lines (per csharp_indent_switch_labels and csharp_indent_case_contents), with BRO1526's blank line between sections. A braced one (if (x) { y; } else z;) keeps its block on one line, with the { and else on their own lines as csharp_new_line_before_open_brace and csharp_new_line_before_else say.
Configuration¶
[*.cs]
# false (default, like StyleCop): empty braces on one line are expanded too.
# true: empty braces on one line ('{ }', whitespace only) stay, for every kind this rule and BRO1508 check.
stylebro_allow_empty_single_line_blocks = false
With true, public Foo() { }, public void OnStart() { }, public class Marker { }, enum None { } and
statement blocks like catch { } (BRO1508 reads the same key) stay on one line; anything with code
inside is still expanded:
public class Hooks { public Hooks() { } public void Stop() { this.Stopped = true; } }
becomes
public class Hooks
{
public Hooks() { }
public void Stop()
{
this.Stopped = true;
}
}
Expanding an enclosing block never touches an allowed empty one inside it. BRO1140 and
BRO1145, when on, still turn an empty record or type body into ;. Not a StyleCop setting (StyleCop
issues #3093 and
#3564 ask for it); stylebro-migrate doesn't write
it. The SDK's csharp_preserve_single_line_blocks only keeps blocks as they are, so it can't enforce either layout.
Not reported¶
- Auto-properties and expression-bodied accessors (
{ get; set; },{ get => x; }), like StyleCop: only an accessor list where an accessor has a body counts. - Single-line accessors inside a multi-line property, like StyleCop.
- A comment inside the braces: the fix would have to move it.
- A comment after the
}on its line (public void Reset() { } // NOSONAR): expanded, the comment would end up on the}line, away from the declaration a line-based suppression marks.
A C# 14 extension block on one line (extension(long v) { public long Half => v / 2; }) is expanded like a type.
Compared with StyleCop¶
Same positions as StyleCop, except a block with a comment after its }. For a local function StyleCop reports both SA1501 and SA1502 at the same brace; StyleBro
reports BRO1509 once. StyleCop's fix leaves accessors and nested declarations side by side on one line, misindents
nested ones, and writes Windows line endings into files that use \n.