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.
Rule 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
How to fix violations
The violation can either be fixed manually, or, in some cases, using Quick Actions to fix code in Visual Studio.
Examples
The following two code snippets show all possible violations of the rule in C# and how to fix them:
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 warnings
It's safe to suppress a violation of this rule if improving code readability is not 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.
#pragma warning disable CA2249
// The code that's violating the rule is on this line.
#pragma warning restore CA2249To disable the rule for a file, folder, or project, set its severity to none in the configuration file.
[*.{cs,vb}]
dotnet_diagnostic.CA2249.severity = noneFor more information, see How to suppress code analysis warnings.