C# Replace String Examples

Use the Replace method to change all instances of one substring to another. Get the modified string.
Replace. A city can be changed. One building can be added and another destroyed. Think of this city as a string. We remove some characters and add new ones.
With Replace we search for (and exchange) one pattern for another. What was before is no longer. A change occurs and a new string is returned.
To begin, we call the Replace method. Please note that we must assign Replace's result to a variable. It does not modify the string in-place.

Here: We introduce a const string literal. We call Replace() on this character data, and it returns a new string object.

WriteLine: We pass the "output" string to Console.WriteLine to print it to the console window.

C# program that uses Replace using System; class Program { static void Main() { const string input = "key tool"; Console.WriteLine("::BEFORE::"); Console.WriteLine(input); // Replace word (and following space) with a new word. // ... We assign to the Replace method's result. string output = input.Replace("key ", "keyword "); Console.WriteLine("::AFTER::"); Console.WriteLine(output); } } Output ::BEFORE:: key tool ::AFTER:: keyword tool
Every instance. This is important. The Replace method changes every instance of the specified substring. This can sometimes result in unexpected behavior. The first match is not targeted.

Here: The console program replaces the substring "green" with the substring "brown." There is no need to call Replace() 2 times.

Note: A second Replace() would not do anything. It would just result in CPU cycles being wasted.

C# program that causes multiple replacements using System; class Program { static void Main() { const string value = "The frog is green and the tree is green."; Console.WriteLine("BEFORE: " + value); // Store the result of Replace() in a variable. // ... All instances of the substring are replaced (not just the first). string modified = value.Replace("green", "brown"); Console.WriteLine("AFTER: " + modified); } } Output BEFORE: The frog is green and the tree is green. AFTER: The frog is brown and the tree is brown.
StringBuilder. This is an important type. With StringBuilder, Replace works the same way as with strings, but we don't need to assign the result to anything.

Here: In this example, we create a StringBuilder. We use the constructor to initialize the StringBuilder with a short sentence.

StringBuilder

Replace: We replace the word "This" with the word "Here." The result has the new word in place of the old word.

C# program that uses StringBuilder using System; using System.Text; class Program { static void Main() { const string value = "This is an example."; // Create new StringBuilder from string. StringBuilder builder = new StringBuilder(value); Console.WriteLine("A: " + builder); // Replace the first word. // ... The result doesn't need assignment. builder.Replace("This", "Here"); Console.WriteLine("B: " + builder); // Insert the string at the beginning. builder.Insert(0, "Sentence: "); Console.WriteLine("C: " + builder); } } Output A: This is an example. B: Here is an example. C: Sentence: Here is an example.
Zero-length error. Most parameters (including null) will not cause an exception in Replace(). But if we try to replace an empty string, an ArgumentException is encountered.

Note: It makes no sense to replace an empty string—would the result (in some cases) be an infinitely long string?

ArgumentException
C# program that causes empty string error class Program { static void Main() { string test = "test"; // Cannot replace an empty string. string result = test.Replace("", ""); } } Output Unhandled Exception: System.ArgumentException: String cannot be of zero length. Parameter name: oldValue at System.String.ReplaceInternal(String oldValue, String newValue) at System.String.Replace(String oldValue, String newValue) at Program.Main() in ...
Problem, copies. Replace() creates a string copy each time it is called. This can lead to measurable performance problems. Microsoft notes that Replace returns a new string.

Quote: This method does not modify the value of the current instance. Instead, it returns a new string in which all occurrences of oldValue are replaced by newValue.

String.Replace Method: Microsoft Docs
Performance, StringBuilder. We can rewrite wasteful string Replace code with StringBuilder. Here we see the original code that uses string and then the new StringBuilder code.

Version 1: This version ends up creating many string copies. It replaces whitespace around punctuation.

NewLineEmpty

Version 2: MinifyWithStringBuilder is similar but uses StringBuilder. It does the same replacements as version 1.

C# program that benchmarks Replace methods using System; using System.Diagnostics; using System.Text; class Program { static string MinifyWithString(string text) { // Use string Replace to remove whitespace. text = text.Replace(" ", string.Empty); text = text.Replace(Environment.NewLine, string.Empty); text = text.Replace("\\t", string.Empty); text = text.Replace(" {", "{"); text = text.Replace("{ ", "{"); text = text.Replace(" :", ":"); text = text.Replace(": ", ":"); text = text.Replace(", ", ","); text = text.Replace("; ", ";"); text = text.Replace(";}", "}"); return text; } static string MinifyWithStringBuilder(string text) { // Use StringBuilder Replace to remove whitespace. StringBuilder builder = new StringBuilder(text); builder.Replace(" ", string.Empty); builder.Replace(Environment.NewLine, string.Empty); builder.Replace("\\t", string.Empty); builder.Replace(" {", "{"); builder.Replace("{ ", "{"); builder.Replace(" :", ":"); builder.Replace(": ", ":"); builder.Replace(", ", ","); builder.Replace("; ", ";"); builder.Replace(";}", "}"); return builder.ToString(); } const int _max = 1000000; static void Main() { const string text = "#paragraph { color: black; width: 90%; }"; Console.WriteLine(MinifyWithString(text)); Console.WriteLine(MinifyWithStringBuilder(text)); // Version 1: use string Replace repeatedly. var s1 = Stopwatch.StartNew(); for (int i = 0; i < _max; i++) { MinifyWithString(text); } s1.Stop(); // Version 2: use StringBuilder Replace() repeatedly. var s2 = Stopwatch.StartNew(); for (int i = 0; i < _max; i++) { MinifyWithStringBuilder(text); } s2.Stop(); Console.WriteLine(((double)(s1.Elapsed.TotalMilliseconds * 1000000) / _max).ToString("0.00 ns")); Console.WriteLine(((double)(s2.Elapsed.TotalMilliseconds * 1000000) / _max).ToString("0.00 ns")); } } Output #paragraph{color:black;width:90%} #paragraph{color:black;width:90%} 1055.00 ns string Replace() 2023.33 ns StringBuilder Replace()
Performance, notes. The version that avoids copies, with StringBuilder, is many times faster. Neither method is close to optimal, as internally each call to Replace must search the string.

Tip: For the optimal replacement method, write a for-loop that tests each char, then appends to a char array or skips the char.

Warning: A custom parsing algorithm is much faster, but will require more effort to maintain and test.

Performance, arguments. Here we test a program that calls Replace in four ways. The first two calls use char arguments. The second two calls use string arguments.

Note: Only the second and the fourth calls require that the string be changed in memory.

Char

Tip: Avoiding an object allocation has a performance benefit. And often this outweighs any extra CPU usage.

Result: Replace calls that use chars are faster. And if no change occurs, Replace will return faster.

C# program that benchmarks Replace arguments using System; using System.Diagnostics; class Program { const int _max = 1000000; static void Main() { string test = "dotnetperls"; var s1 = Stopwatch.StartNew(); for (int i = 0; i < _max; i++) { string t = test.Replace('x', 'y'); } s1.Stop(); var s2 = Stopwatch.StartNew(); for (int i = 0; i < _max; i++) { string t = test.Replace('d', 'y'); } s2.Stop(); var s3 = Stopwatch.StartNew(); for (int i = 0; i < _max; i++) { string t = test.Replace("x", "y"); } s3.Stop(); var s4 = Stopwatch.StartNew(); for (int i = 0; i < _max; i++) { string t = test.Replace("d", "y"); } s4.Stop(); Console.WriteLine(((double)(s1.Elapsed.TotalMilliseconds * 1000 * 1000) / _max).ToString("0.00 ns")); Console.WriteLine(((double)(s2.Elapsed.TotalMilliseconds * 1000 * 1000) / _max).ToString("0.00 ns")); Console.WriteLine(((double)(s3.Elapsed.TotalMilliseconds * 1000 * 1000) / _max).ToString("0.00 ns")); Console.WriteLine(((double)(s4.Elapsed.TotalMilliseconds * 1000 * 1000) / _max).ToString("0.00 ns")); Console.Read(); } } Output 13.00 ns Char Replace, no change 47.75 ns Char Replace, change 73.26 ns String Replace, no change 117.07 ns String Replace, change
Logic optimization. Replace can be optimized. Suppose in our program many string replacements must be done. But often nothing is changed in actual strings.

Version A: Let's look at the initial version of the method. It runs four Replace calls on the formal parameter to the method.

Version B: The second version uses the Contains method around all the Replace calls with the specified common string literal.

Contains

Tip: In version B, the first two Replace calls are only run when the common pattern is found. Often the string is searched less.

First version of method: C# static string A(string text) { text = text.Replace("<span>Cat ", "<span>Cats "); text = text.Replace("<span>Clear ", "<span>Clears "); text = text.Replace("<span>Dog ", "<span>Dogs "); text = text.Replace("<span>Draw ", "<span>Draws "); return text; } Second version of method: C# static string B(string text) { if (text.Contains("<span>C")) { text = text.Replace("<span>Cat ", "<span>Cats "); text = text.Replace("<span>Clear ", "<span>Clears "); } if (text.Contains("<span>D")) { text = text.Replace("<span>Dog ", "<span>Dogs "); text = text.Replace("<span>Draw ", "<span>Draws "); } return text; }
Regex.Replace. The string.Replace() method is limited in the kinds of substrings it can match. With Regex we can match met a-characters like "digit" or "non-word."Regex.Replace

Here: We replace all strings starting with the word "bird" and ending with a digit char and a non-word char (like a space).

Tip: A custom string parsing method could be written, and the result would likely be faster than Regex.Replace—but it would be more work.

C# program that uses Regex.Replace using System; using System.Text.RegularExpressions; class Program { static void Main() { string value = "bird0 cat1 bird2 cat2 bird."; Console.WriteLine("BEFORE: " + value); // Match all strings starting with "bird" and ending with a digit and non-word character. // ... Replace them with an empty string literal. string result = Regex.Replace(value, @"bird\d\W", ""); Console.WriteLine("AFTER: " + result); } } Output BEFORE: bird0 cat1 bird2 cat2 bird. AFTER: cat1 cat2 bird.
Split. Often strings contains invalid syntax. We can use Replace to fix incorrect parts of a string before using Split to separate it.Split
Whitespace. We often need to remove or change whitespace in strings, particularly those read in from files. We can handle tabs, spaces and line breaks.WhitespaceRegex.Replace: Spaces
A summary. As strings are immutable, Replace does not modify them. It instead creates a new copy with the replacements applied. It replaces all instances of a match.
For frequent replacement, StringBuilder is much faster. It avoids copies. Other than implementation, the methods are used in a similar way, with the same arguments.
© 2007-2019 Sam Allen. Every person is special and unique. Send bug reports to info@dotnetperls.com.
HomeSearch
Home
Dot Net Perls