Microsoft .NET Code Analysis: Choosing Between String.Contains() and String.IndexOf()

For improved readability, Microsoft recommends utilizing String.Contains() over String.IndexOf(). The following code example illustrates this recommendation:

private static bool Contains(string haystack, string needle)
  => haystack.IndexOf(needle, StringComparison.OrdinalIgnoreCase) >= 0;

Utilize String.Contains() to check for the presence or absence of a substring, as demonstrated below:

private static bool Contains(string haystack, string needle)
  => haystack.Contains(needle, StringComparison.OrdinalIgnoreCase);

I wondered if developers were aware of the fastest method to check for a substring within a string, so I conducted a poll on Twitter.

Here are the reasons why using Contains() should be preferred:

  1. Less Error-Prone: Contains reduces the chance of off-by-one errors or other mistakes related to index calculations that can occur when using IndexOf.
  2. Performance: In most cases, Contains can be as performant as IndexOf when it comes to checking for the presence of a substring. If you need to find the index of the substring or need to check for multiple occurrences, IndexOf might be more efficient as you can start searching from a specific position within the string.
  3. Readability and Intent: Contains expresses the intent more clearly in code. When you see Contains("substring"), it’s immediately obvious that you are checking for the presence of “substring” within the string. IndexOf returns an integer index, which might require an additional check to determine if the substring was found as shown in the example above.
  4. Simplicity: Contains is simpler to use since it returns a Boolean indicating whether the substring is present or not. IndexOf returns the index of the first occurrence of the substring (or -1 if not found), which might require extra code to handle properly.

Benchmark Results

In these results, it is evident that utilizing Contains() is 1.57 times faster than employing IndexOf() with AsSpan(), and it outperforms using IndexOf() by 8.14 times in terms of speed.

When I setup the CA2249 code analysis in my .editorConfig it looks like this: dotnet_diagnostic.CA2249.severity = error

Summary

While reviewing the Entity Framework codebase I utilized for this article, I discovered 6 occurrences where the code needs to be fixed.

For further guidance and insights, I highly recommend obtaining a copy of my book, “Rock Your Code: Coding Standards for Microsoft .NET” available on Amazon.com. Additionally, to explore more performance tips for .NET, I encourage you to acquire the 3rd edition of “Rock Your Code: Code & App Performance for Microsoft .NET” also available on Amazon.com.

To analyze your code using the same settings I used in these articles, I encourage you to incorporate my EditorConfig file. It can be found at the following link: https://bit.ly/dotNetDaveEditorConfig. I update this file quarterly, so remember to keep yours up to date as well. I hope you will check out my OSS project Spargine by using this link: https://bit.ly/Spargine.

Please feel free to leave a comment below. I would appreciate hearing your thoughts and feedback.

Pick up any books by David McCarter by going to Amazon.com: http://bit.ly/RockYourCodeBooks

One-Time
Monthly
Yearly

Make a one-time donation

Make a monthly donation

Make a yearly donation

Choose an amount

$5.00
$15.00
$100.00
$5.00
$15.00
$100.00
$5.00
$15.00
$100.00

Or enter a custom amount

$

Your contribution is appreciated.

Your contribution is appreciated.

Your contribution is appreciated.

DonateDonate monthlyDonate yearly

If you liked this article, please buy David a cup of Coffee by going here: https://www.buymeacoffee.com/dotnetdave

© The information in this article is copywritten and cannot be preproduced in any way without express permission from David McCarter.

Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.