CA1833: Use AsSpan or AsMemory instead of Range-based indexers for getting Span or Memory portion of an array

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

Cause

When using a range-indexer on an array and implicitly assigning the value to Span<T> or Memory<T>.

Rule description

Using a range-indexer on array and assigning to a memory or span type: The range indexer on a Span<T> is a non-copying Slice operation, but for the range indexer on array the method GetSubArray will be used instead of Slice, which produces a copy of requested portion of the array. This copy is usually unnecessary when it is implicitly used as a Span<T> or Memory<T> value. If a copy isn't intended, use the AsSpan or AsMemory 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 conversions:

  • Span<SomeT> slice = arr[a..b];
  • Memory<SomeT> slice = arr[a..b];

Does not detect

Explicit conversions:

  • Span<SomeT> slice = (Span<SomeT>)arr[a..b];
  • Memory<SomeT> slice = (Memory<SomeT>)arr[a..b];

How to fix violations

To fix the violation of this rule: use the AsSpan or AsMemory extension method to avoid creating unnecessary data copies.

class C
{
    public void TestMethod(byte[] arr)
    {
        // The violation occurs for both statements below
        Span<byte> tmp2 = arr[0..5];
        Memory<byte> tmp4 = arr[5..10];
        ...
    }
}
class C
{
    public void TestMethod(byte[] arr)
    {
        // The violations fixed with AsSpan or AsMemory accordingly
        Span<byte> tmp2 = arr.AsSpan()[0..5];
        Memory<byte> tmp4 = arr.AsMemory()[5..10];
        ...
    }
}

Tip

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

Code fix for CA1833 - Use AsSpan or AsMemory instead of Range-based indexers for getting Span or Memory portion of an array

You can also avoid this warning by adding an explicit cast.

class C
{
    public void TestMethod(byte arr[])
    {
        // The violation occurs
        Span<byte> tmp1 = arr[0..5];
        Memory<byte> tmp2 = arr[5..10];
        ...
    }
}
class C
{
    public void TestMethod(byte arr[])
    {
        // The violation fixed with explicit casting
        Span<byte> tmp1 = (Span<byte>)arr[0..5];
        Memory<byte> tmp2 = (Memory<byte>)arr[5..10];
        ...
    }
}

When to suppress warnings

It's safe to suppress a violation of this rule if creating a copy is intended.

Suppress a warning

If you just want to suppress a single violation, add preprocessor directives to your source file to disable and then re-enable the rule.

#pragma warning disable CA1833
// The code that's violating the rule is on this line.
#pragma warning restore CA1833

To disable the rule for a file, folder, or project, set its severity to none in the configuration file.

[*.{cs,vb}]
dotnet_diagnostic.CA1833.severity = none

To disable this entire category of rules, set the severity for the category to none in the configuration file.

[*.{cs,vb}]
dotnet_analyzer_diagnostic.category-Performance.severity = none

For more information, see How to suppress code analysis warnings.

See also