Login


A Case-Insensitive Version of String.Replace()

By Jonathan Wood on 9/26/2012
Language: C#
Technology: .NET
Platform: Windows
License: CPOL
Views: 33,510
General Programming » Text Handling » General » A Case-Insensitive Version of String.Replace()

Introduction

The String.Replace() method allows you to easily replace a substring with another substring, or a character with another character, within the contents of a String object.

This method is very handy, but it is always case-sensitive. So I thought it would be interesting to create a case-insensitive version of this method.

A Custom Version of String.Replace()

Listing 1 shows my modified version of String.Replace(). It's implemented as an extension method so it will behave as a built-in method of the String class. The String class has two overloads of this method, one to replace strings and another to replace characters. So if my extension method is visible to your code, it will appear as if the String class has three overloads for the Replace() method. (Note that I did not implement a case-insensitive overload of the character replacement version.)

My version of Replace() takes the substring to find and the replacement substring (just as the original version of Replace() does) along with a StringComparison argument, which specifies the search type.

The code passes the actual case-insentive searching logic off to the String.IndexOf() method, which also accepts a StringComparison argument. If IndexOf() finds a match, my code copies any portion of the string that comes before the match and appends it to my resulting string (implemented as a StringBuilder object). It then appends the replacement string (newValue). This is repeated as long as additional matches are found. When no more matches are found, the code copies the remaining characters to the result string and, finally, returns that result string.

Listing 1: A Case-Insensitive Version of String.Replace()

/// <summary>
/// Case insensitive version of String.Replace().
/// </summary>
/// <param name="s">String that contains patterns to replace</param>
/// <param name="oldValue">Pattern to find</param>
/// <param name="newValue">New pattern to replaces old</param>
/// <param name="comparisonType">String comparison type</param>
/// <returns></returns>
public static string Replace(this string s, string oldValue, string newValue,
    StringComparison comparisonType)
{
    if (s == null)
        return null;

    if (String.IsNullOrEmpty(oldValue))
        return s;

    StringBuilder result = new StringBuilder(Math.Min(4096, s.Length));
    int pos = 0;

    while (true)
    {
        int i = s.IndexOf(oldValue, pos, comparisonType);
        if (i < 0)
            break;

        result.Append(s, pos, i - pos);
        result.Append(newValue);

        pos = i + oldValue.Length;
    }
    result.Append(s, pos, s.Length - pos);

    return result.ToString();
}

Conclusion

As mentioned, since my code is implemented as an extension method, it can be called as though it was a built-in method of the String class. I've demonstrated this in Listing 2.

Listing 2: Using the Case-Insensitive Version of String.Replace()

String s = "abcdef";
// Call the built-in Replace() method
s = s.Replace("abc", "123");
// Call my Replace() extension method
s = s.Replace("DEF", "456", StringComparison.OrdinalIgnoreCase);

And that's all there is to it.

I should point out that the RegEx class can also be used to accomplish this task if you prefer to use that. For me, the code I've presented above seems simpler. Also, I haven't done any performance tests but suspect my code might be a little faster than using RegEx.

End-User License

Use of this article and any related source code or other files is governed by the terms and conditions of The Code Project Open License.

Author Information

Jonathan Wood

I'm a software/website developer working out of the greater Salt Lake City area in Utah. I've developed many websites including Black Belt Coder, Insider Articles, and others.