BRO1302: Parameter names should begin with a lower-case letter¶
Parameters are camelCase: count, not Count or _count. Replaces StyleCop SA1313.
Example¶
Before¶
internal abstract class Shape
{
/// <summary>Scales the shape.</summary>
/// <param name="Factor">How much to scale by.</param>
public abstract void Scale(double Factor);
}
internal class Circle : Shape
{
public double Radius { get; private set; } = 1;
public override void Scale(double Factor) => Radius *= Factor;
public static Circle Create() => new Circle().Resized(Factor: 2);
private Circle Resized(double Factor)
{
Scale(Factor);
return this;
}
}
After¶
internal abstract class Shape
{
/// <summary>Scales the shape.</summary>
/// <param name="factor">How much to scale by.</param>
public abstract void Scale(double factor);
}
internal class Circle : Shape
{
public double Radius { get; private set; } = 1;
public override void Scale(double factor) => Radius *= factor;
public static Circle Create() => new Circle().Resized(factor: 2);
private Circle Resized(double factor)
{
Scale(factor);
return this;
}
}
Why¶
C# names locals and parameters in camelCase and everything else in PascalCase, so the case tells you at a glance whether a name belongs to the method. For parameters it's also part of the API: callers see the names in IntelliSense and use them in named arguments.
Configuration¶
stylebro_rename_public_api = true also renames names other assemblies see (default false, see Not reported; the owner's decision in decisions.md).
How the fix works¶
The parameter and every use of it are renamed, anywhere in the solution: the body, nameof, named arguments
(Resized(Factor: 2)) and the <param>/<paramref> docs. The new name is built like for
BRO1301: Count becomes count, _count becomes count, URL becomes url, MAX_COUNT becomes maxCount.
A parameter of an abstract, virtual or interface member takes the parameters of its overrides and implementations along when they have the same name, so they stay in sync. Those parameters aren't reported themselves (their name comes from the base, like in StyleCop); one that has a different name is reported on its own.
Checked: parameters of methods, constructors (including primary constructors of classes and structs), indexers, operators, delegates, local functions, lambdas and anonymous methods.
Renaming a public parameter is a source-breaking change for callers outside the solution that use it as a named argument. Code inside the solution is updated.
The name can reach run time. nameof(Path) becomes nameof(path), and ArgumentNullException.ThrowIfNull(Path)
reads the name through [CallerArgumentExpression], so an exception's ParamName changes from "Path" to "path".
Like StyleCop's SA1313 fix, the rename goes ahead: the new name is what the parameter is called now, and a test that
compares ParamName with the old spelling needs the same update. (BRO1313 is different: it renames a parameter that
already has a consistent name only to match its base, so it keeps such names; see decisions.md.)
Not reported¶
- Where IDE1006 is suppressed: after
#pragma warning disable IDE1006(up to itsrestore), or with[SuppressMessage("Style", "IDE1006")]on the declaration, its member or type, or a global one targeting them. Code that opts out of the SDK's naming rules (a file copied from another project) keeps its names. - A new name your SDK naming rule rejects: when the first
dotnet_naming_rulethat covers the symbol is enforced (IDE1006, or the rule's own severity, at suggestion or above) and asks for another style, like_camelCasefor private properties, the name stays (renaming it would only trade this warning for IDE1006). - Public API (unless
stylebro_rename_public_api = true): Parameters of methods, constructors, indexers and delegates that other assemblies see, that is public, protected or protected internal in types that are visible too. Renaming them breaks code outside the solution (named arguments use parameter names). Internal code is renamed, also withInternalsVisibleTo. - A name that
nameof(...)produces: the rename would change the string (Ocelot built an HTTP header name withnameof(X_RateLimit_Limit), and a test read a private field withGetField(nameof(_components))). Looked for in the member for variables and parameters, in the type for fields; the fix also looks in the rest of the solution and leaves the warning when it finds one. - Record parameters (
record Person(string Name)): they become properties, which are PascalCase. - Parameters that keep the name of the parameter they override or implement.
- Partial methods. Both declarations have to be renamed together.
- Constructor parameters named exactly like a property or field of their type (
Point(int X) { this.X = X; }). Serializers bind constructor parameters to members by name, and some (CsvHelper) case-sensitively, soX->xwould compile and then fail to load data. Found through CsvHelper's tests. - Names in an expression tree: parameters of a lambda that end up in a
System.Linq.Expressionstree (anExpression<Func<...>>lambda, a query method onIQueryable, or a lambda nested in one). The names are data at run time: they show in the expression'sToString()and query providers may use them (Mapster's tests compare a query's text). StyleCop's SA1313 reports them. - The same unsafe cases as BRO1301: the new name is already used in the member, two names would get
the same new name, the parameter names an anonymous type member or tuple element by inference, the member contains
#if, or the name has no camelCase form (_,_1,Class,Field), or would bevaluein an indexer.
When an override can't be renamed safely (its member already uses the new name), the base and the other overrides are renamed and that override keeps its name.
Reported but not fixed¶
If dotnet format leaves a finding, StyleBro kept it on purpose. The fix looks at the whole solution, other
projects included, which the analyzer can't see, and leaves a change that would break something there: the name in a
string or a nameof (reflection, serialization), a member that would hide it, a use in generated code. It offers no
code action for such a finding, and stylebro-migrate format lists each one with its reason
(Findings kept on purpose); its --verify-no-changes doesn't fail on
them. Change it by hand only after checking those uses, or suppress it or record it in the baseline.
Compared with StyleCop¶
Same results as StyleCop, except for the skipped cases above; StyleCop reports _ and __ parameters. StyleCop's fix
for SA1313 only lowers the first letter, can't fix names that start with _, leaves overrides and implementations
behind (they are then reported), and under dotnet format applies only some of the renames per run.