Table of Contents

SA1003: Symbols should be spaced correctly

Cause

The spacing around an operator symbol is incorrect, within a C# code file.

Rule description

A violation of this rule occurs when the spacing around an operator symbol is incorrect.

The following types of operator symbols should be surrounded by a single space on either side: colons, arithmetic operators, assignment operators, conditional operators, logical operators, relational operators, shift operators, and lambda operators. For example:

int x = 4 + y;

Starting with C# 8.0, the lambda operator => also appears in switch expression arms. The same spacing rules apply: each arrow should have a single space on both sides.

var description = value switch { 0 => "zero", _ => "nonzero" };

Relational operators inside pattern matching expressions follow the same rules when they appear after keywords such as is. For example, in a relational pattern the > in value is > 5 must be surrounded by spaces: value is > 5. When a relational pattern is wrapped in parentheses, it should still avoid spaces immediately after ( or before ), consistent with the parenthesis rules described in SA1008.

In contrast, unary operators should be preceded by a single space, but should never be followed by any space. For example:

bool x = !value;

An exception occurs whenever the symbol is preceded or followed by a parenthesis or bracket, in which case there should be no space between the symbol and the bracket. For example:

if (!value)
{
}

Starting with C# 8.0, a null-forgiving operator (!) may appear at the end of a line after any expression. Postfix increment and decrement operators (++ and --) may also appear at the end of a line when the next token begins on a new line. A null-forgiving operator is also written without a space before element access. For example:

Print(
    value: nullableValue! // trailing comment
);

var result = nullableValue!
    .ToString();

var item = nullableArray![0];

var incrementedValue = GetCounter().Value++
    + 2;

The C# 8 index-from-end operator (^) follows the same unary spacing requirements. It is written adjacent to its operand without a trailing space, and no additional space is inserted after [ or ( when it appears immediately after one of those tokens. Examples:

var last = values[^1];
Index start = ^5;

The C# 8 range operator (..) is treated as a binary operator which should not be surrounded by a single space on either side. Within indexers, this spacing is applied between operands while still omitting any space after [ or before ]. For example:

Range middle = 1..4;
var slice = values[1..^2];

How to fix violations

To fix a violation of this rule, ensure that the spacing around the symbol follows the rule described above.

For a constructor initializer whose colon appears at the end of a line, the code fix moves the colon to the next line with the initializer and preserves its indentation:

public MyType()
    : base(3)
{
}

How to suppress violations

[SuppressMessage("StyleCop.CSharp.SpacingRules", "SA1003:SymbolsMustBeSpacedCorrectly", Justification = "Reviewed.")]
#pragma warning disable SA1003 // SymbolsMustBeSpacedCorrectly
#pragma warning restore SA1003 // SymbolsMustBeSpacedCorrectly