Skip to content

Commit 78968f0

Browse files
authored
Merge pull request #37056 from MihaZupan/ca1870
Add documentation for CA1870
2 parents 6551282 + a16d883 commit 78968f0

File tree

4 files changed

+104
-0
lines changed

4 files changed

+104
-0
lines changed
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
---
2+
title: "CA1870: Use a cached 'SearchValues' instance"
3+
description: "Learn about code analyzer rule CA1870 - Use a cached 'SearchValues' instance"
4+
ms.date: 09/12/2023
5+
ms.topic: reference
6+
f1_keywords:
7+
- CA1870
8+
- UseSearchValuesAnalyzer
9+
helpviewer_keywords:
10+
- CA1870
11+
dev_langs:
12+
- CSharp
13+
author: MihaZupan
14+
ms.author: mizupan
15+
---
16+
17+
# CA1870: Use a cached 'SearchValues' instance
18+
19+
| Property | Value |
20+
|-------------------------------------|----------------------------------------|
21+
| **Rule ID** | CA1870 |
22+
| **Title** | Use a cached 'SearchValues' instance |
23+
| **Category** | [Performance](performance-warnings.md) |
24+
| **Fix is breaking or non-breaking** | Non-breaking |
25+
| **Enabled by default in .NET 8** | Yes |
26+
27+
## Cause
28+
29+
An `IndexOfAny` or `ContainsAny` method is called with many constant values in a way that can benefit from using <xref:System.Buffers.SearchValues> instead.
30+
31+
The rule doesn't flag calls that use up to five values, as those already use an optimal implementation.
32+
33+
## Rule description
34+
35+
Using a cached <xref:System.Buffers.SearchValues%601> instance is more efficient than passing values to `IndexOfAny` or `ContainsAny` directly.
36+
37+
## How to fix violations
38+
39+
Create and cache a <xref:System.Buffers.SearchValues%601> instance in a `static readonly` field, then pass that instance to the `IndexOfAny` or `ContainsAny` call instead.
40+
41+
A code fixer that performs this transformation is available.
42+
43+
## Example
44+
45+
The following code snippet shows two violations of CA1870:
46+
47+
```csharp
48+
static readonly char[] MyValues = new[] { 'a', 'b', 'c', 'x', 'y', 'z' };
49+
50+
static int IndexOfMyValues(ReadOnlySpan<char> text)
51+
{
52+
return text.IndexOfAny(MyValues);
53+
}
54+
55+
static bool ContainsOnlyMyValues(ReadOnlySpan<char> text)
56+
{
57+
return !text.ContainsAnyExcept("abcxyz");
58+
}
59+
```
60+
61+
The following code snippet fixes the violations:
62+
63+
```csharp
64+
private static readonly SearchValues<char> s_myValues = SearchValues.Create("abcxyz");
65+
66+
static int IndexOfMyValues(ReadOnlySpan<char> text)
67+
{
68+
return text.IndexOfAny(s_myValues);
69+
}
70+
71+
static bool ContainsOnlyMyValues(ReadOnlySpan<char> text)
72+
{
73+
return !text.ContainsAnyExcept(s_myValues);
74+
}
75+
```
76+
77+
If there are multiple calls to `IndexOfAny` with the same set of values, `s_myValues` should be reused.
78+
79+
## When to suppress warnings
80+
81+
It's safe to suppress this warning if performance isn't a concern.
82+
83+
## Suppress a warning
84+
85+
If you just want to suppress a single violation, add preprocessor directives to your source file to disable and then re-enable the rule.
86+
87+
```csharp
88+
#pragma warning disable CA1870
89+
// The code that's violating the rule is on this line.
90+
#pragma warning restore CA1870
91+
```
92+
93+
To disable the rule for a file, folder, or project, set its severity to `none` in the [configuration file](../configuration-files.md).
94+
95+
```ini
96+
[*.{cs,vb}]
97+
dotnet_diagnostic.CA1870.severity = none
98+
```
99+
100+
For more information, see [How to suppress code analysis warnings](../suppress-warnings.md).

docs/fundamentals/code-analysis/quality-rules/index.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,7 @@ The following table lists code quality analysis rules.
161161
> | [CA1865-CA1867: Use char overload](ca1865-ca1867.md) | The char overload is a better performing overload for a string with a single char. |
162162
> | [CA1868: Unnecessary call to 'Contains' for sets](ca1868.md) | Both <xref:System.Collections.Generic.ISet%601.Add(%600)?displayProperty=nameWithType> and <xref:System.Collections.Generic.ICollection%601.Remove(%600)?displayProperty=nameWithType> perform a lookup, which makes it redundant to call <xref:System.Collections.Generic.ICollection%601.Contains(%600)?displayProperty=nameWithType> beforehand. It's more efficient to call <xref:System.Collections.Generic.ISet%601.Add(%600)> or <xref:System.Collections.Generic.ICollection%601.Remove(%600)> directly, which returns a Boolean value indicating whether the item was added or removed. |
163163
> | [CA1869: Cache and reuse 'JsonSerializerOptions' instances](ca1869.md) | Using a local instance of <xref:System.Text.Json.JsonSerializerOptions> for serialization or deserialization can substantially degrade the performance of your application if your code executes multiple times, since System.Text.Json internally caches serialization-related metadata into the provided instance. |
164+
> | [CA1870: Use a cached 'SearchValues' instance](ca1870.md) | Using a cached <xref:System.Buffers.SearchValues%601> instance is more efficient than passing values to 'IndexOfAny' or 'ContainsAny' directly. |
164165
> | [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. |
165166
> | [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. |
166167
> | [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. |

docs/fundamentals/code-analysis/quality-rules/performance-warnings.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,3 +74,4 @@ Performance rules support high-performance libraries and applications.
7474
| [CA1865-CA1867: Use char overload](ca1865-ca1867.md) | The char overload is a better performing overload for a string with a single char. |
7575
| [CA1868: Unnecessary call to 'Contains' for sets](ca1868.md) | Both <xref:System.Collections.Generic.ISet%601.Add(%600)?displayProperty=nameWithType> and <xref:System.Collections.Generic.ICollection%601.Remove(%600)?displayProperty=nameWithType> perform a lookup, which makes it redundant to call <xref:System.Collections.Generic.ICollection%601.Contains(%600)?displayProperty=nameWithType> beforehand. It's more efficient to call <xref:System.Collections.Generic.ISet%601.Add(%600)> or <xref:System.Collections.Generic.ICollection%601.Remove(%600)> directly, which returns a Boolean value indicating whether the item was added or removed. |
7676
| [CA1869: Cache and reuse 'JsonSerializerOptions' instances](ca1869.md) | Using a local instance of <xref:System.Text.Json.JsonSerializerOptions> for serialization or deserialization can substantially degrade the performance of your application if your code executes multiple times, since System.Text.Json internally caches serialization-related metadata into the provided instance. |
77+
| [CA1870: Use a cached 'SearchValues' instance](ca1870.md) | Using a cached <xref:System.Buffers.SearchValues%601> instance is more efficient than passing values to 'IndexOfAny' or 'ContainsAny' directly. |

docs/navigate/tools-diagnostics/toc.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -812,6 +812,8 @@ items:
812812
href: ../../fundamentals/code-analysis/quality-rules/ca1868.md
813813
- name: CA1869
814814
href: ../../fundamentals/code-analysis/quality-rules/ca1869.md
815+
- name: CA1870
816+
href: ../../fundamentals/code-analysis/quality-rules/ca1870.md
815817
- name: SingleFile rules
816818
items:
817819
- name: Overview

0 commit comments

Comments
 (0)