Skip to content

BRO1308: Field names should not contain an underscore

Fields are named maxValue or MaxValue, not max_value or Max_Value. Replaces StyleCop SA1310.

Example

Before

internal class Throttle
{
    public const int Max_Requests = 100;
    private int request_count;

    public bool TryEnter()
    {
        if (request_count >= Max_Requests)
        {
            return false;
        }

        request_count++;
        return true;
    }
}

After

internal class Throttle
{
    public const int MaxRequests = 100;
    private int requestCount;

    public bool TryEnter()
    {
        if (requestCount >= MaxRequests)
        {
            return false;
        }

        requestCount++;
        return true;
    }
}

Why

C# separates words by capital letters, not underscores. Max_Requests and request_count are habits from C and other languages.

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 field is renamed everywhere. The words between the underscores are joined, and the casing follows the field's kind: PascalCase for constants, static readonly and non-private fields (BRO1306), camelCase for private fields (or _camelCase, see BRO1303) and protected fields. A word in all capitals counts as a word, not an acronym: Max_HTTP_Requests becomes MaxHttpRequests, request_count becomes requestCount, trailing_ becomes trailing.

A leading underscore isn't this rule's business (it's BRO1303's or BRO1306's), and a m_/s_/t_ prefix is BRO1307's, which also removes any underscores after it.

A name starting with _ is only joined where the underscore goes too (the camelCase style: _signature_size becomes signatureSize in one rename). In the _camelCase style it's left alone, like StyleCop's SA1310, which doesn't check a name starting with _: _signature_size stays (SSH.NET, StyleCop-clean, kept such names).

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.
  • Public API (unless stylebro_rename_public_api = true): 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. 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.
  • Names that would become a keyword.
  • Fields in a class whose name ends in NativeMethods (or a type nested in one), like StyleCop: they hold Win32 and COM names.
  • Interop names (owner's decision in decisions.md): a SCREAMING_CASE constant or static readonly field (S_OK, MAX_PATH), a COM GUID field (IID_IContextMenu, CLSID_ShellLink), and every field of a type that looks like interop, or of a type nested in one: [StructLayout], [ComImport], [UnmanagedFunctionPointer], or [DllImport]/[LibraryImport] methods. The same goes for BRO1303, BRO1306, BRO1307 and BRO1310.
  • The same unsafe cases as BRO1303: a member with the new name, two fields getting the same name, attributes or a [Serializable] type, the name in a string (for public instance fields, anywhere inside a string, since serializers write them by name), in #if-excluded code, or as an inferred anonymous type member or tuple element 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 fields as StyleCop, minus the interop names above (StyleCop reports MAX_PATH). StyleCop's fix only deletes the underscores: MAX_VALUE becomes MAXVALUE.