Skip to content
Merged
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
98 changes: 98 additions & 0 deletions docs/fundamentals/code-analysis/quality-rules/ca1858.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
---
title: "CA1858: Use StartsWith instead of IndexOf"
description: "Learn about code analyzer rule CA1858 - Use StartsWith instead of IndexOf"
ms.date: 12/20/2022
ms.topic: reference
f1_keywords:
- CA1858
- UseStartsWithInsteadOfIndexOfComparisonWithZero
helpviewer_keywords:
- CA1858
dev_langs:
- CSharp
- VB
---

# CA1858: Use StartsWith instead of IndexOf

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

## Cause

<xref:System.String.IndexOf%2A?displayProperty=nameWithType> is called and its result is compared against zero.

## Rule description

It's more efficient and clearer to call <xref:System.String.StartsWith%2A?displayProperty=nameWithType> than to call <xref:System.String.IndexOf%2A?displayProperty=nameWithType> and compare the result with zero to determine whether a string starts with a given prefix.

`IndexOf` searches the entire string, while `StartsWith` only compares at the beginning of the string.

## How to fix violations

Replace the call to <xref:System.String.IndexOf%2A?displayProperty=nameWithType> with a call to <xref:System.String.StartsWith%2A?displayProperty=nameWithType>.

## Example

The following code snippet shows a violation of CA1855:

```csharp
bool M(string s)
{
return s.IndexOf("abc") == 0;
}
```

```vb
Function M(s As String) As Boolean
Return s.IndexOf("abc") = 0
End Function
```

The following code snippet fixes the violation:

```csharp
bool M(string s)
{
return s.StartsWith("abc");
}
```

```vb
Function M(s As String) As Boolean
Return s.StartsWith("abc")
End Function
```

## When to suppress warnings

It's safe to suppress this warning if performance isn't a concern.

## 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.

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

To disable the rule for a file, folder, or project, set its severity to `none` in the [configuration file](../configuration-files.md).

```ini
[*.{cs,vb}]
dotnet_diagnostic.CA1858.severity = none
```

To disable this entire category of rules, set the severity for the category to `none` in the [configuration file](../configuration-files.md).

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

For more information, see [How to suppress code analysis warnings](../suppress-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 @@ -151,6 +151,7 @@ The following table lists code quality analysis rules.
> | [CA1853: Unnecessary call to 'Dictionary.ContainsKey(key)'](ca1853.md) | There's no need to guard `Dictionary.Remove(key)` with `Dictionary.ContainsKey(key)`. <xref:System.Collections.Generic.Dictionary%602.Remove(%600)?displayProperty=nameWithType> already checks whether the key exists and doesn't throw if it doesn't exist. |
> | [CA1854: Prefer the 'IDictionary.TryGetValue(TKey, out TValue)' method](ca1854.md) | Prefer 'TryGetValue' over a Dictionary indexer access guarded by a 'ContainsKey' check. 'ContainsKey' and the indexer both look up the key, so using 'TryGetValue' avoids the extra lookup. |
> | [CA1855: Use Span\<T>.Clear() instead of Span\<T>.Fill()](ca1855.md) | It's more efficient to call <xref:System.Span%601.Clear?displayProperty=nameWithType> than to call <xref:System.Span%601.Fill(%600)?displayProperty=nameWithType> to fill the elements of the span with a default value. |
> | [CA1858: Use StartsWith instead of IndexOf](ca1858.md) | It's more efficient to call <xref:System.String.StartsWith%2A?displayProperty=nameWithType> than to call <xref:System.String.IndexOf%2A?displayProperty=nameWithType> to check whether a string starts with a given prefix. |
> | [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 @@ -66,3 +66,4 @@ Performance rules support high-performance libraries and applications.
| [CA1853: Unnecessary call to 'Dictionary.ContainsKey(key)'](ca1853.md) | There's no need to guard `Dictionary.Remove(key)` with `Dictionary.ContainsKey(key)`. <xref:System.Collections.Generic.Dictionary%602.Remove(%600)?displayProperty=nameWithType> already checks whether the key exists and doesn't throw if it doesn't exist. |
| [CA1854: Prefer the 'IDictionary.TryGetValue(TKey, out TValue)' method](ca1854.md) | Prefer 'TryGetValue' over a Dictionary indexer access guarded by a 'ContainsKey' check. 'ContainsKey' and the indexer both look up the key, so using 'TryGetValue' avoids the extra lookup. |
| [CA1855: Use Span\<T>.Clear() instead of Span\<T>.Fill()](ca1855.md) | It's more efficient to call <xref:System.Span%601.Clear?displayProperty=nameWithType> than to call <xref:System.Span%601.Fill(%600)?displayProperty=nameWithType> to fill the elements of the span with a default value. |
| [CA1858: Use StartsWith instead of IndexOf](ca1858.md) | It's more efficient to call <xref:System.String.StartsWith%2A?displayProperty=nameWithType> than to call <xref:System.String.IndexOf%2A?displayProperty=nameWithType> to check whether a string starts with a given prefix. |
2 changes: 2 additions & 0 deletions docs/fundamentals/toc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1177,6 +1177,8 @@ items:
href: code-analysis/quality-rules/ca1854.md
- name: CA1855
href: code-analysis/quality-rules/ca1855.md
- name: CA1858
href: code-analysis/quality-rules/ca1858.md
- name: SingleFile rules
items:
- name: Overview
Expand Down