CA1831: Use AsSpan instead of Range-based indexers for string when appropriate

Value
Rule ID CA1831
Category Performance
Fix is breaking or non-breaking Non-breaking

Cause

A range-indexer is used on a string and the value is implicitly assigned to ReadOnlySpan<char>.

Rule description

This rule fires when you use a range-indexer on a string and assign it to a span type. The range indexer on a Span<T> is a non-copying Slice operation, but for the range indexer on a string, the method Substring will be used instead of Slice. This produces a copy of the requested portion of the string. This copy is usually unnecessary when it's implicitly used as a ReadOnlySpan<T> or ReadOnlyMemory<T> value. If a copy isn't intended, use the AsSpan method to avoid the unnecessary copy. If the copy is intended, either assign it to a local variable first or add an explicit cast. The analyzer only reports when an implicit cast is used on the result of the range indexer operation.

Detects

Implicit conversion:

ReadOnlySpan<char> slice = str[a..b];

Does not detect

Explicit conversion:

ReadOnlySpan<char> slice = (ReadOnlySpan<char>)str[a..b];

How to fix violations

To fix a violation of this rule, use AsSpan instead of the Range-based indexer on the string to avoid creating unnecessary data copies.

public void TestMethod(string str)
{
    // The violation occurs
    ReadOnlySpan<char> slice = str[1..3];
    ...
}
public void TestMethod(string str)
{
    // The violation fixed with AsSpan extension method
    ReadOnlySpan<char> slice = str.AsSpan()[1..3];
    ...
}

Tip

A code fix is available for this rule in Visual Studio. To use it, position the cursor on the array violation and press Ctrl+. (period). Choose Use AsSpan instead of the Range-based indexer on a string from the list of options that's presented.

Code fix for CA1831 - Use AsSpan instead of Range-based indexers when appropriate

When to suppress warnings

It's safe to suppress a violation of this rule if creating a copy is intended. Other than the usual ways to suppress code analysis warnings, you can also add an explicit cast to avoid the warning.

public void TestMethod(string str)
{
    // The violation occurs.
    ReadOnlySpan<char> slice = str[1..3];
    ...
}
public void TestMethod(string str)
{
    // The violation avoided with explicit casting.
    ReadOnlySpan<char> slice = (ReadOnlySpan<char>)str[1..3];
    ...
}

See also