Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ca1846 #24325

Merged
merged 8 commits into from
May 27, 2021
Merged

Ca1846 #24325

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
77 changes: 77 additions & 0 deletions docs/fundamentals/code-analysis/quality-rules/ca1846.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
---
title: "CA1846: Prefer `AsSpan` over `Substring`"
description: "Learn about code analysis rule CA1846: Prefer `AsSpan` over `Substring`"
ms.date: 05/21/2021
ms.topic: reference
f1_keywords:
- CA1846
- PreferAsSpanOverSubstring
helpviewer_keywords:
- PreferAsSpanOverSubstring
- CA1846
author: NewellClark
dev_langs:
- CSharp
- VB
gewarren marked this conversation as resolved.
Show resolved Hide resolved
---
# CA1846: Prefer `AsSpan` over `Substring`

| | Value |
|-|-|
| **Rule ID** |CA1846|
| **Category** |[Performance](performance-warnings.md)|
| **Fix is breaking or non-breaking** |Non-breaking|

## Cause

The result of a call to one of the <xref:System.String.Substring%2A?displayProperty=nameWithType> overloads is passed to a method with an available overload that accepts `ReadOnlySpan<Char>`.

## Rule description

`Substring` allocates a new `string` object on the heap and performs a full copy of the extracted text. String manipulation is a performance bottleneck for many programs. Allocating many small, short-lived strings on a hot path can create enough collection pressure to impact performance. The O(n) copies created by `Substring` become relevant when the substrings get large. The <xref:System.Span%601> and <xref:System.ReadOnlySpan%601> types were created to solve these performance problems.

Many APIs that accept strings also have overloads that accept a `ReadOnlySpan<System.Char>` argument. When such overloads are available, you can improve performance by calling `AsSpan` instead of `Substring`.

## How to fix violations

To fix a violation of this rule, replace the call to `string.Substring` with a call to one of the <xref:System.MemoryExtensions.AsSpan%2A?displayProperty=nameWithType> extension methods.

```csharp
gewarren marked this conversation as resolved.
Show resolved Hide resolved
using System;

public void MyMethod(string iniFileLine)
{
// Violation
int.TryParse(iniFileLine.Substring(7), out int x);
int.TryParse(iniFileLine.Substring(2, 5), out int y);

// Fix
int.TryParse(iniFileLine.AsSpan(7), out int x);
int.TryParse(iniFileLine.AsSpan(2, 5), out int y);
}
```

```vb
Imports System

Public Sub MyMethod(iniFileLine As String)
Dim x As Integer
Dim y As Integer

' Violation
Integer.TryParse(iniFileLine.Substring(7), x)
Integer.TryParse(iniFileLine.Substring(2, 5), y)

' Fix
Integer.TryParse(iniFileLine.AsSpan(7), x)
Integer.TryParse(iniFileLine.AsSpan(2, 5), y)
End Sub
```

## When to suppress warnings

It is safe to suppress warnings from this rule if performance is not a concern.

## See also

- [Performance warnings](performance-warnings.md)
1 change: 1 addition & 0 deletions docs/fundamentals/code-analysis/quality-rules/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ The following table lists code quality analysis rules.
> | [CA1838: Avoid `StringBuilder` parameters for P/Invokes](ca1838.md) | Marshaling of 'StringBuilder' always creates a native buffer copy, resulting in multiple allocations for one marshaling operation. |
> | [CA1841: Prefer Dictionary Contains methods](ca1841.md) | Calling `Contains` on the `Keys` or `Values` collection may often be more expensive than calling `ContainsKey` or `ContainsValue` on the dictionary itself. |
> | [CA1845: Use span-based 'string.Concat'](ca1845.md) | It is more efficient to use `AsSpan` and `string.Concat`, instead of `Substring` and a concatenation operator. |
> | [CA1846: Prefer `AsSpan` over `Substring`](ca1846.md) | `AsSpan` is more efficient than `Substring`. `Substring` performs an O(n) string copy, while `AsSpan` does not and has a constant cost. `AsSpan` also does not perform any heap allocations. |
> | [CA2000: Dispose objects before losing scope](ca2000.md) | Because an exceptional event might occur that will prevent the finalizer of an object from running, the object should be explicitly disposed before all references to it are out of scope. |
> |[CA2002: Do not lock on objects with weak identity](ca2002.md) |An object is said to have a weak identity when it can be directly accessed across application domain boundaries. A thread that tries to acquire a lock on an object that has a weak identity can be blocked by a second thread in a different application domain that has a lock on the same object. |
> | [CA2007: Do not directly await a Task](ca2007.md) | An asynchronous method [awaits](../../../csharp/language-reference/operators/await.md) a <xref:System.Threading.Tasks.Task> directly. When an asynchronous method awaits a <xref:System.Threading.Tasks.Task> directly, continuation occurs in the same thread that created the task. This behavior can be costly in terms of performance and can result in a deadlock on the UI thread. Consider calling <xref:System.Threading.Tasks.Task.ConfigureAwait(System.Boolean)?displayProperty=nameWithType> to signal your intention for continuation. |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,3 +51,4 @@ Performance rules support high-performance libraries and applications.
| [CA1838: Avoid `StringBuilder` parameters for P/Invokes](ca1838.md) | Marshaling of `StringBuilder` always creates a native buffer copy, resulting in multiple allocations for one marshaling operation. |
| [CA1841: Prefer Dictionary Contains methods](ca1841.md) | Calling `Contains` on the `Keys` or `Values` collection may often be more expensive than calling `ContainsKey` or `ContainsValue` on the dictionary itself. |
| [CA1845: Use span-based 'string.Concat'](ca1845.md) | It is more efficient to use `AsSpan` and `string.Concat`, instead of `Substring` and a concatenation operator. |
| [CA1846: Prefer `AsSpan` over `Substring`](ca1846.md) | `AsSpan` is more efficient than `Substring`. `Substring` performs an O(n) string copy, while `AsSpan` does not and has a constant cost. `AsSpan` also does not perform any heap allocations. |
2 changes: 2 additions & 0 deletions docs/fundamentals/toc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -884,6 +884,8 @@ items:
href: code-analysis/quality-rules/ca1841.md
- name: CA1845
href: code-analysis/quality-rules/ca1845.md
- name: CA1846
href: code-analysis/quality-rules/ca1846.md
- name: SingleFile rules
items:
- name: Overview
Expand Down