TheDeveloperBlog.com


C# Char Lowercase Optimization

Char lowercase. A character can be lowercased with various algorithms. Some approaches are faster than others. And some approaches handle special cases better than others. Here we see alternative lower and upper C# methods on char, with a benchmark.

Benchmark
Optimized ways to lowercase characters

char.ToLower: 10704 ms   (Framework)
ToLowerIf:     1231 ms   (If-statement)
ToLowerFast:    563 ms   (Lookup table)


Example. Here we see a C# class that can lowercase and uppercase a char in two different ways. The Framework methods, char.ToLower and char.ToUpper, work on a wider range of characters than these, which only work on ASCII characters.

char.ToLower Methods
Class that implements lowercase optimization: C#

/// <summary>
/// Contains character-level methods.
/// </summary>
public static class CharTool
{
    /// <summary>
    /// Converts characters to lowercase.
    /// </summary>
    const string _lookupStringL =
"---------------------------------!-#$%&-()*+,-./0123456789:;<=>?@abcdefghijklmnopqrstuvwxyz[-]^_`abcdefghijklmnopqrstuvwxyz{|}~-";

    /// <summary>
    /// Converts characters to uppercase.
    /// </summary>
    const string _lookupStringU =
"---------------------------------!-#$%&-()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[-]^_`ABCDEFGHIJKLMNOPQRSTUVWXYZ{|}~-";

    /// <summary>
    /// Get lowercase version of this ASCII character.
    /// </summary>
    public static char ToLowerFast(char c)
    {
	return _lookupStringL[c];
    }

    /// <summary>
    /// Get uppercase version of this ASCII character.
    /// </summary>
    public static char ToUpperFast(char c)
    {
	return _lookupStringU[c];
    }

    /// <summary>
    /// Translate uppercase characters to lowercase characters.
    /// </summary>
    public static char ToLowerFastIf(char c)
    {
	if (c >= 'A' && c <= 'Z')
	{
	    return (char)(c + 32);
	}
	else
	{
	    return c;
	}
    }

    /// <summary>
    /// Translate lowercase ASCII characters to uppercase.
    /// </summary>
    public static char ToUpperFastIf(char c)
    {
	if (c >= 'a' && c <= 'z')
	{
	    return (char)(c - 32);
	}
	else
	{
	    return c;
	}
    }
}

The strings in the class contains the uppercase or lowercase versions of the characters corresponding to each index. You can use look up 'a' and receive an 'A'. When you lookup a value that cannot be uppercased, it is returned unchanged.

Tip: You can find more information on the char data type to explain this optimization.


Summary. We saw that using char.ToLower is significantly slower than the method that tests each character with an if-statement. Finally, the method that uses a lookup table is somewhat faster than the second method.

Note: In most deployed C# applications, these timings are insignificant. But this optimization is sometimes useful.