All rules
CA2249Usage Enabled by default: As suggestion

Consider using String.Contains instead of String.IndexOf

Consider using String.Contains instead of String.IndexOf

Microsoft docs

Description

When System.String.IndexOf is used to check if the result is equal to -1 or greater or equal than 0, the call can be safely substituted with System.String.Contains without an impact on performance.

Depending on the System.String.IndexOf overload being used, the suggested fix could get a comparisonType argument added:

| Overload | Suggested fix | | -------------------------------------------------------- | ---------------------------------------------------------- | | String.IndexOf(char) | String.Contains(char) | | String.IndexOf(string) | String.Contains(string, StringComparison.CurrentCulture) | | String.IndexOf(char, StringComparison.Ordinal) | String.Contains(char) | | String.IndexOf(string, StringComparison.Ordinal) | String.Contains(string) | | String.IndexOf(char, NON StringComparison.Ordinal)\* | String.Contains(char, NON StringComparison.Ordinal)\* | | String.IndexOf(string, NON StringComparison.Ordinal)\* | String.Contains(string, NON StringComparison.Ordinal)\* |

\* Any StringComparison enum value other than StringComparison.Ordinal:

  • System.StringComparison.CurrentCulture
  • System.StringComparison.CurrentCultureIgnoreCase
  • System.StringComparison.InvariantCulture
  • System.StringComparison.InvariantCultureIgnoreCase
  • System.StringComparison.OrdinalIgnoreCase

Cause

This rule locates calls to System.String.IndexOf where the result is used to check for the presence or absence of a substring, and suggests using System.String.Contains instead, to improve readability.

How to fix violations

The violation can either be fixed manually, or, in some cases, using Quick Actions to fix code in Visual Studio.

Example

using System;

class MyClass
{
    void MyMethod()
    {
        string str = "My text";
        bool found;

        // No comparisonType in char overload, so no comparisonType added in resulting fix
        found = str.IndexOf('x') == -1;
        found = str.IndexOf('x') >= 0;

        // No comparisonType in string overload, adds StringComparison.CurrentCulture to resulting fix
        found = str.IndexOf("text") == -1;
        found = str.IndexOf("text") >= 0;

        // comparisonType equal to StringComparison.Ordinal, removes the argument
        found = str.IndexOf('x', StringComparison.Ordinal) == -1;
        found = str.IndexOf('x', StringComparison.Ordinal) >= 0;

        found = str.IndexOf("text", StringComparison.Ordinal) == -1;
        found = str.IndexOf("text", StringComparison.Ordinal) >= 0;

        // comparisonType different than StringComparison.Ordinal, preserves the argument
        found = str.IndexOf('x', StringComparison.OrdinalIgnoreCase) == -1;
        found = str.IndexOf('x', StringComparison.CurrentCulture) >= 0;

        found = str.IndexOf("text", StringComparison.InvariantCultureIgnoreCase) == -1;
        found = str.IndexOf("text", StringComparison.InvariantCulture) >= 0;

        // Suggestion message provided, but no automatic fix offered, must be fixed manually
        int index = str.IndexOf("text");
        if (index == -1)
        {
            Console.WriteLine("'text' Not found.");
        }
    }
}

using System;

class MyClass
{
    void MyMethod()
    {
        string str = "My text";
        bool found;

        // No comparisonType in char overload, so no comparisonType added in resulting fix
        found = !str.Contains('x');
        found = str.Contains('x');

        // No comparisonType in string overload, adds StringComparison.CurrentCulture to resulting fix
        found = !str.Contains("text", StringComparison.CurrentCulture);
        found = str.Contains("text", StringComparison.CurrentCulture);

        // comparisonType equal to StringComparison.Ordinal, removes the argument
        found = !str.Contains('x');
        found = str.Contains('x');

        found = !str.Contains("text");
        found = str.Contains("text");

        // comparisonType different than StringComparison.Ordinal, preserves the argument
        found = !str.Contains('x', StringComparison.OrdinalIgnoreCase);
        found = str.Contains('x', StringComparison.CurrentCulture);

        found = !str.Contains("text", StringComparison.InvariantCultureIgnoreCase);
        found = str.Contains("text", StringComparison.InvariantCulture);

        // This case had to be manually fixed
        if (!str.Contains("text"))
        {
            Console.WriteLine("'text' Not found.");
        }
    }
}

When to suppress

It's safe to suppress a violation of this rule if improving code readability is not a concern.

Group results
0 yes 0 no
ConsensusNone (disabled)
Severity preference (yes voters)
Suggestion0
Warning0
Error0