Skip to content

BRO1401: Use a trailing comma in multi-line initializers

The last item of a multi-line list should be followed by a comma. Replaces StyleCop SA1413.

Example

Before

public enum Status
{
    Active,
    Closed
}

public class Settings
{
    public string[] Hosts { get; } = new[]
    {
        "alpha",
        "beta"
    };
}

After

public enum Status
{
    Active,
    Closed,
}

public class Settings
{
    public string[] Hosts { get; } = new[]
    {
        "alpha",
        "beta",
    };
}

Why

With a trailing comma, adding an item at the end changes one line instead of two, and moving items around never leaves a missing comma behind.

What is reported

Like StyleCop, these lists, when their braces are on different lines:

  • array, object and collection initializers (new[] { ... }, new Point { ... }, new List<int> { ... })
  • with { ... } expressions and anonymous objects
  • enums and switch expressions

Configuration

[*.cs]
# include (default): a trailing comma after the last item of a multi-line list (StyleCop's SA1413).
# omit: no trailing comma after the last item of any list, single-line ones included.
stylebro_trailing_comma = include

With omit the rule reports the trailing comma instead, in the same kinds of lists, and the fix removes it:

public enum Status
{
    Active,
    Closed, // last
}

var hosts = new[] { "alpha", "beta", };

becomes

public enum Status
{
    Active,
    Closed // last
}

var hosts = new[] { "alpha", "beta" };

Unlike include, omit checks single-line lists too (like Roslynator's RCS1260 with omit): a comma there never saves a diff line. Spaces before the removed comma go with it, and a trailing comment keeps its place. Lists with a directive between their braces are still skipped. BRO1509 and BRO1121, which put a one-line enum's values on their own lines, then don't add the trailing comma either. Not a StyleCop setting (StyleCop issue #2260 questions the rule); stylebro-migrate doesn't write it.

How the fix works

The comma goes right after the last item's code, so before a trailing comment: "beta" // last becomes "beta", // last. When code follows the item directly ("beta"};), the fix inserts , so the comma gets the space after it that the formatter expects. Nested lists get all their commas in one dotnet format run.

Not reported

  • Lists with a preprocessor directive between their braces, such as an item inside #if. Which item is last then depends on the build configuration, and in a multi-targeted project each target framework would need a different edit to the same file.
  • Collection expressions [ ... ], list patterns, property patterns (o is Point { ... }, nested ones too), and { key, value } pairs in a dictionary initializer, like StyleCop 1.2.0-beta.556.

Compared with StyleCop

Property patterns aren't checked, like StyleCop 1.2.0-beta.556; StyleCop's unreleased master reports multi-line ones (94671b70), which put a comma after every closing } of a nested pattern ({ Identifier.ValueText: "Requires" }, then }, and }, in microsoft/vs-validation). The owner chose the release (decisions, 2026-10-11). StyleCop also reports lists with #if inside. Its fix writes "beta",}; without a space, and needs a second run for nested lists.