C# IndexOf

IndexOf

IndexOf searches strings. It returns the first occurrence of a letter in a string. It can also find a substring in the string. It is often used in looping constructs. It returns negative one when nothing is found.

Intro

First, there are four IndexOf instance methods. The first two methods find the first indexes. They scan through the characters from the left to right. The second two find the last indexes, and they go from right to left.

Methods

IndexOf:This method finds the first index of the char argument. It returns -1 if the char was not found.

IndexOfAny:This method finds the first index of any of the char arguments. It returns -1 if none are found.

Index

LastIndexOf:This finds the last index of the char argument. It also returns -1 if the char was not found.

LastIndexOfAny:This finds the first index of any of the char arguments. It also returns -1 if none are found.

Example

String type

In this example, we use IndexOf simply to see whether the input string contains a string. We want to see if the string in the example contains "Vader". We test the result of IndexOf against the special constant -1.

Here:The input string in part A is what we want to test. In part B, it calls the IndexOf method.

And:IndexOf returns the location of the string "Vader". It is not equal to -1, so the line is written to the console window.

C# program that uses IndexOf

using System;

class Program
{
    static void Main()
    {
	// A.
	// The input string.
	const string s = "Darth Vader is really scary.";

	// B.
	// Test with IndexOf.
	if (s.IndexOf("Vader") != -1)
	{
	    Console.Write("string contains 'Vader'");
	}
	Console.ReadLine();
    }
}

Output

string contains 'Vader'

Loop

While keyword

Here we use the IndexOf instance method in loops. To do this, keep track of several values at once. You can loop through the instances of a char in a string. Here we loop over each 'a' in the string.

C# program that uses IndexOf in loop

using System;

class Program
{
    static void Main()
    {
	// A.
	// The input string.
	string s = "I have a cat";

	// B.
	// Loop through all instances of the letter a.
	int i = 0;
	while ((i = s.IndexOf('a', i)) != -1)
	{
	    // C.
	    // Print out the substring.
	    Console.WriteLine(s.Substring(i));

	    // D.
	    // Increment the index.
	    i++;
	}
	Console.ReadLine();
    }
}

Output

ave a cat
a cat
at
Arrow indicates looping

In this program, part A has an input string—this is what we are testing with IndexOf.
In part B,
it uses a while-loop,
which is the best way to do this. We test it for success each time. If the character is not found, the loop ends.

While

Next, in part C, it writes the result to the console with WriteLine. You do not need this part but it writes the Substring specified by the index and count arguments. In part D, the index is incremented.

Console.WriteLine

Tip:We must advance past the current character by adding one to the index. If you do not do this, you will get an infinite loop.

Return value

Return keyword

The return value of IndexOf is -1 when it does not find anything, and the index if it does. This is not an ideal design. I have caused an IndexOutOfRangeException by using the -1 in other code.

So:Please be careful when using IndexOf. It is probably better to check for negative one at least once in most places.

Substring

Substring method example

We next use the IndexOf method with the Substring method. Here we get the first substring that begins with a certain pattern or character. The Substring method returns the rest of the string starting at your specified number.

Substring
C# program that uses Substring

using System;

class Program
{
    static void Main()
    {
	// Input.
	const string s = "I have a cat";

	// Location of the letter c.
	int i = s.IndexOf('c');

	// Remainder of string starting at 'c'.
	string d = s.Substring(i);
	Console.WriteLine(d);
	Console.ReadLine();
    }
}

Output

cat

IndexOfAny

Any method

IndexOfAny searches for the first index of any of the characters provided in the char array parameter. This method is the same as calling IndexOf several times with the logical OR operator. It has different performance characteristics.

IndexOfAny

LastIndexOf

Method

You can use LastIndexOf to search the source string just like IndexOf. The LastIndexOf and LastIndexOfAny methods work the same way but in reverse. They still return -1 if the char cannot be found. These are much less frequently used.

Tip:You can find more information on the LastIndexOf method on the string type.

LastIndexOf

Benchmark

Performance optimization

Here we test the IndexOf method against a single character iteration for-loop. I wanted to know if scanning through a string with a single char loop was faster than using IndexOf over each character.

And:I found it is more efficient to scan each character individually than to use IndexOf.

Note:Using IndexOf is more complex. It may therefore be harder to optimize for the compiler.

Char version: C#

int c = 0;
for (int e = 0; e < s.Length; e++)
{
    if (s[e] == '.')
    {
	c++;
    }
}

IndexOf version: C#

int c = 0;
int e = 0;
while ((e = s.IndexOf('.', e)) != -1)
{
    e++;
    c++;
}

Results

Char version:    1545 ms
IndexOf version: 2215 ms

For-loop

Programming tip

You can replace character iteration loops with IndexOf in some situations. This can result in much clearer code, but there will be some performance impact. The second code example may clearer for some developers.

For loop version: C#

int number = -1;
for (int y = 0; y < value.Length; y++)
{
    if (value[y] == '1')
    {
	number = y;
	break;
    }
}

IndexOf version: C#

int number = value.IndexOf('1');

Because I had nothing better to do, I executed these two pieces of code and tested their performance in tight loops. The imperative for-loop was faster by a couple nanoseconds. If you are desperate for performance, this can help.

Results
    Test string literal is "something-1-two".

For loop: 11.19 ns
IndexOf:  14.01 ns

Arguments

Char type

Is there is a difference between calling IndexOf with a single character string argument, and with a char argument? If you call IndexOf with a string, globalization rules will be applied.

Therefore:The string IndexOf will require more CPU cycles. But even if you pass in StringComparison.Ordinal, it is slower.

So:The underlying implementation for the form that uses a char argument is more efficient.

IndexOf usage with string: C#

int i = s.IndexOf("a");
// Finds first "a" string in s.

IndexOf usage with char: C#

int i = s.IndexOf('a');
// Finds first 'a' char in s.

Results
    Ten million tests.

String version: 1154 ms
Char version:    172 ms

From this test, I found that calling IndexOf with a string is nearly ten times slower than calling it with a character. This is the case even with a single-character string. The character overload should be used when possible.

Contains

True

Contains is a wrapper method. It calls IndexOf with StringComparison.Ordinal.
It returns true
or false,
not an integer. If its internal IndexOf returns -1, it returns false, otherwise it returns true.

Contains
IndexOf and Contains

IndexOf found result:     index
Contains:                 true 

IndexOf not found result: -1   
Contains:                 false

Summary

Method call

IndexOf is a powerful method. You will commonly use it to search for chars (or substrings) in your strings. There is no built-in string method called Search. But the general idea is performed by IndexOf.


C#: String