TheDeveloperBlog.com


C# String For-Loop

String for-loop. For loops over characters in strings. Some code examples use an inefficient string loop pattern. This causes unnecessary allocations on the managed heap. These loops can be improved and simplified.


Example. Initially here we look at two loops over a single string reference's character data. Each loop compares each character in the source string against the space character. The first loop is much faster and results in fewer allocations.

And: The second loop draws in the overhead of creating new string objects based on each character.

Note: This is a clear mistake, but one that is made often in code examples on the Internet and in many real programs.

C# program that uses for-loops on input string

using System;

class Program
{
    static void Main()
    {
	string input = "Dot Net Perls website";
	//
	// Check each character in the string using for-loop.
	//
	int spaces1 = 0;
	for (int i = 0; i < input.Length; i++)
	{
	    if (input[i] == ' ')
	    {
		spaces1++;
	    }
	}
	//
	// BAD: Check each character in the string with ToString calls.
	//
	int spaces2 = 0;
	for (int i = 0; i < input.Length; i++)
	{
	    if (input[i].ToString() == " ") // NO
	    {
		spaces2++;
	    }
	}
	//
	// Write results.
	//
	Console.WriteLine(spaces1);
	Console.WriteLine(spaces2);
    }
}

Output

3
3

The first loop uses a for-loop statement with an if-statement in its body. If the character is a space, the value stored in the spaces1 variable is incremented. In this way, the for-loop counts the number of spaces.

Note: No allocations on the managed heap occur and this is a well-performing loop over the string.

The second loop in the program text also uses a for-loop statement to iterate over the characters in the string. However, after accessing the character value, it calls the ToString method.

ToString

Warning: This requires an allocation of a new string on the managed heap, because strings are reference types.

Then: The op_Equality method is invoked on the two string instances in the loop body. This loop is slower because it allocate strings.


Benchmark. The for-loop that uses direct character comparisons is far faster, nearly ten times faster, than the for-loop that invokes the ToString method. After the benchmark results, we note another common string loop mistake.

Benchmark
Benchmark description

Iterations:             10000000
Input string:           "Dot Net Perls website"
Loop bodies:            Same as in top example.
Character testing loop:  46.50 ns
ToString loop:          445.11 ns
Summary:                Using ToString was nearly ten times slower.

Also, the ToString loop here has similarities to a pattern occasionally used by developers that loops over the string by taking a one-character substring. This results in a string allocation because it demands a new string reference.

Note: If you are testing characters, you also do not need to do this. Loops that use Substring will be much slower.

Substring

Summary. Chars should be directly tested in string loops. Developers who are accustomed to other languages (like Java) where character iteration is different sometimes make looping mistakes. This is likely due to unfamiliarity.

Loop Over String Chars