BRO1105: Constructor initializers should be on their own line¶
: base(...) and : this(...) go on the line after the constructor's parameters, one level deeper. Replaces
StyleCop SA1128.
Example¶
Before¶
public class Entity
{
public Entity(string id)
{
Id = id;
}
public string Id { get; }
}
public class Customer : Entity
{
public Customer(string id, string name) : base(id)
{
Name = name;
}
public string Name { get; }
}
After¶
public class Entity
{
public Entity(string id)
{
Id = id;
}
public string Id { get; }
}
public class Customer : Entity
{
public Customer(string id, string name)
: base(id)
{
Name = name;
}
public string Name { get; }
}
Why¶
Constructor signatures tend to get long. With the initializer on its own line, the parameters and the call to the other constructor are each easy to read, and changing one doesn't touch the other's line.
How the fix works¶
The indentation comes from .editorconfig (indent_style, indent_size, tab_width) and defaults to four spaces.
Everything after base/this stays as it is: the arguments, even when they span several lines, and a body on the
same line (: base() { }). A comment before the colon stays on the constructor's line. A colon at the end of the
constructor's line (Customer(...) :) moves down too.
Not reported¶
- An initializer that already starts its line.
- A primary constructor's base list (
class D(int x) : B(x)), which isn't a constructor initializer. - A comment between the colon and
base/this(: /* note */ base()). The fix rewrites exactly that stretch, so it would drop the comment.
Configuration¶
[*.cs]
stylebro_constructor_initializer_placement = own_line
own_line(default): like StyleCop's SA1128, as described above.same_line: the initializer goes on the line of the parameter list's):
// Before
public Customer(string id, string name)
: base(id)
{
}
// After
public Customer(string id, string name) : base(id)
{
}
With same_line, an initializer is only joined (and only reported) when:
- the line of the
)with: base(...)added, up to the initializer's end, fitsmax_line_length. A body after the initializer ({ },=> ...) isn't counted: BRO1509 may move it. Withoutmax_line_lengththere is no limit, so set it when you usesame_line. - the initializer is on one line (
base(with arguments on further lines is left alone), - nothing but whitespace sits between
)andbase/this(no comments or directives).
When the parameter list is split, the initializer goes after the ) on its last line. A ) on its own line that
BRO1110 moves to the last parameter moves in the same edit (int b) : base(b)), so both fixes give the
same text whichever runs first. The ) line is measured as the other fixes in the same run leave it, when those rules
are on: BRO1404/BRO1007 add an access modifier, BRO1109 moves ( up,
BRO1108 puts each parameter on its own line, BRO1110 moves ) (its own_line setting
puts it on a line of its own, where the initializer then joins it). So the decision doesn't depend on which fix runs
first. Not counted: renames (BRO1302, BRO1309, ...) and rewrites inside the line
(BRO1115 int?, BRO1144 @, ...), whose results depend on checks made elsewhere (a
rename can be skipped). Right at the limit, one of those can still leave a join for a second dotnet format run, or
a joined line a few characters too long.
Compared with StyleCop¶
Same results as StyleCop. StyleCop has no same_line setting; teams that prefer it turn SA1128 off.