Skip to content

BRO1310: Field names should not use Hungarian notation

Variable, parameter and field names don't start with a type prefix: count, not iCount. Replaces StyleCop SA1305. Off by default, like StyleCop's.

Example

root = true

[*.cs]
dotnet_diagnostic.BRO1310.severity = warning

Before

internal class Order
{
    private int nItems;

    public string Describe(string szCustomer, bool isPaid)
    {
        var strTotal = nItems.ToString();
        return szCustomer + ": " + strTotal + (isPaid ? " (paid)" : string.Empty);
    }
}

After

internal class Order
{
    private int items;

    public string Describe(string customer, bool isPaid)
    {
        var strTotal = items.ToString();
        return customer + ": " + strTotal + (isPaid ? " (paid)" : string.Empty);
    }
}

Why

A prefix repeats the type, which the compiler and the editor already know, and goes stale when the type changes.

Configuration

# Prefixes that are fine (StyleCop's allowedHungarianPrefixes).
stylebro_allowed_hungarian_prefixes = db, ui

# StyleCop's list of common words that look like prefixes (as, at, by, do, go, if, in, is, it, no, of, on, or, to)
# is allowed unless this is false (allowCommonHungarianPrefixes).
stylebro_allow_common_hungarian_prefixes = true

stylebro-migrate writes both from stylecop.json.

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

A prefix is what StyleCop counts as one: one or two lower-case letters followed by an upper-case letter (iCount, szName; strName has three letters and isn't one). The fix removes it and lowers the rest like BRO1301: pURL becomes url. It's the same rename as the other naming rules, with the same safety checks, so _iCount gets one rename to count (or _count with stylebro_private_field_naming = _camelCase), reported as BRO1310.

Not reported

  • Where IDE1006 is suppressed: after #pragma warning disable IDE1006 (up to its restore), 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_rule that covers the symbol is enforced (IDE1006, or the rule's own severity, at suggestion or above) and asks for another style, like _camelCase for private properties, the name stays (renaming it would only trade this warning for IDE1006).
  • Public API (unless stylebro_rename_public_api = true): Parameters and protected fields 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 with InternalsVisibleTo.
  • A name that nameof(...) produces: the rename would change the string (Ocelot built an HTTP header name with nameof(X_RateLimit_Limit), and a test read a private field with GetField(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.
  • Classes whose name ends in NativeMethods, like StyleCop: Win32 names (lpBuffer, dwFlags) stay.
  • Interop names: SCREAMING_CASE constants and static readonly fields (S_OK), COM GUID fields (IID_...), and the fields of interop-shaped types ([StructLayout], [ComImport], [DllImport] methods); see BRO1308.
  • Parameters of extern, [DllImport] and [LibraryImport] methods and local functions: they keep the native API's names (hWnd, dwFlags), like BRO1309 leaves the methods' names alone.
  • Parameters that keep a base method's or interface's name, record parameters, partial methods, like BRO1302.
  • Constants, static readonly, public and internal fields: they are PascalCase (BRO1306), so xPos becomes XPos there and no longer has a prefix.
  • Another name in the member would get the same new name: xItem and yItem in one query, or a parameter nSize in a method named Size. Renaming one would collide with the other, or take two runs.
  • Any case the other naming rules skip (the new name is taken, the name appears in a string, ...).

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

StyleCop has no fix for SA1305. It reports constant, static readonly and public fields too; StyleBro reports those as BRO1306 and renames them to PascalCase, which also removes the prefix's lower-case form. StyleCop doesn't look past a leading underscore (_iCount), but once SA1309 removes it SA1305 reports iCount; StyleBro reports _iCount right away and renames it once. StyleCop reports the parameters of P/Invoke methods outside a NativeMethods class (#2859, open); StyleBro doesn't.