C#idiomatic C#
modifycsharp/fundamentals/strings/common-tasks

Language

Modify string contents in C#

Learn how to produce modified strings in C# with Replace, Trim, Remove, regular expressions, and character arrays, and why each operation returns a new string.

  • page csharp/fundamentals/strings/common-tasks/modify
  • updated 06/24/2026

A C# string is immutable, which means its contents never change after you create it. Every method that appears to modify a string actually returns a new string with the changes, leaving the original intact. The examples in this article store each result in a new variable so you can see both the source and the modified value.

Choose the technique that matches your scenario: replace known text, trim whitespace, remove a span of characters, replace text that matches a pattern, or edit individual characters.

Replace known text

The System.String.Replace method substitutes every occurrence of one string with another and returns the result as a new string:

sample · csharpdocs/csharp/fundamentals/strings/common-tasks/snippets/modify/Program.csReplace

csharp
using System.Text.RegularExpressions;

namespace ModifyStrings;

public static class Program
{
    public static void Main()
    {
        ReplaceText();
        Console.WriteLine();
        ReplaceCharacters();
        Console.WriteLine();
        TrimWhitespace();
        Console.WriteLine();
        RemoveText();
        Console.WriteLine();
        ReplaceWithRegex();
        Console.WriteLine();
        ModifyCharacters();
    }

    private static void ReplaceText()
    {
        // <Replace>
        string source = "The mountains are behind the clouds today.";

        // Replace returns a new string; the original is unchanged.
        string updated = source.Replace("mountains", "peaks");

        Console.WriteLine(source);
        // => The mountains are behind the clouds today.
        Console.WriteLine(updated);
        // => The peaks are behind the clouds today.
        // </Replace>
    }

    private static void ReplaceCharacters()
    {
        // <ReplaceChar>
        string source = "The mountains are behind the clouds today.";

        // Replace every occurrence of one character with another.
        string updated = source.Replace(' ', '_');

        Console.WriteLine(updated);
        // => The_mountains_are_behind_the_clouds_today.
        // </ReplaceChar>
    }

    private static void TrimWhitespace()
    {
        // <Trim>
        string source = "    I'm wider than I need to be.      ";

        // Each method returns a new string with whitespace removed.
        Console.WriteLine($"<{source.Trim()}>");
        // => <I'm wider than I need to be.>
        Console.WriteLine($"<{source.TrimStart()}>");
        // => <I'm wider than I need to be.      >
        Console.WriteLine($"<{source.TrimEnd()}>");
        // => <    I'm wider than I need to be.>
        // </Trim>
    }

    private static void RemoveText()
    {
        // <Remove>
        string source = "Many mountains are behind many clouds today.";
        string toRemove = "many ";

        // Find the text, then remove that span by index and length.
        int index = source.IndexOf(toRemove);
        string result = index >= 0
            ? source.Remove(index, toRemove.Length)
            : source;

        Console.WriteLine(result);
        // => Many mountains are behind clouds today.
        // </Remove>
    }

    private static void ReplaceWithRegex()
    {
        // <Regex>
        string source = "The mountains are still there behind the clouds today.";

        // Replace "the" or "The" followed by whitespace, preserving the original case.
        // The \s in the pattern keeps "there" from matching.
        string result = Regex.Replace(
            source,
            """the\s""",
            match => char.IsUpper(match.Value[0]) ? "Many " : "many ",
            RegexOptions.IgnoreCase);

        Console.WriteLine(result);
        // => Many mountains are still there behind many clouds today.
        // </Regex>
    }

    private static void ModifyCharacters()
    {
        // <CharArray>
        string phrase = "The quick brown fox jumps over the fence.";

        // A string is immutable, so copy it into a Span<char> to edit in place.
        Span<char> characters = stackalloc char[phrase.Length];
        phrase.CopyTo(characters);
        int index = phrase.IndexOf("fox");
        if (index != -1)
        {
            characters[index] = 'c';
            characters[index + 1] = 'a';
            characters[index + 2] = 't';
        }

        // Build a new string from the modified characters.
        string updated = new string(characters);
        Console.WriteLine(updated);
        // => The quick brown cat jumps over the fence.
        // </CharArray>
    }
}

The original string is unchanged, which demonstrates immutability: Replace creates a new string with the substitution.

Replace also has an overload that swaps single characters. The following example replaces every space with an underscore:

sample · csharpdocs/csharp/fundamentals/strings/common-tasks/snippets/modify/Program.csReplaceChar

csharp
using System.Text.RegularExpressions;

namespace ModifyStrings;

public static class Program
{
    public static void Main()
    {
        ReplaceText();
        Console.WriteLine();
        ReplaceCharacters();
        Console.WriteLine();
        TrimWhitespace();
        Console.WriteLine();
        RemoveText();
        Console.WriteLine();
        ReplaceWithRegex();
        Console.WriteLine();
        ModifyCharacters();
    }

    private static void ReplaceText()
    {
        // <Replace>
        string source = "The mountains are behind the clouds today.";

        // Replace returns a new string; the original is unchanged.
        string updated = source.Replace("mountains", "peaks");

        Console.WriteLine(source);
        // => The mountains are behind the clouds today.
        Console.WriteLine(updated);
        // => The peaks are behind the clouds today.
        // </Replace>
    }

    private static void ReplaceCharacters()
    {
        // <ReplaceChar>
        string source = "The mountains are behind the clouds today.";

        // Replace every occurrence of one character with another.
        string updated = source.Replace(' ', '_');

        Console.WriteLine(updated);
        // => The_mountains_are_behind_the_clouds_today.
        // </ReplaceChar>
    }

    private static void TrimWhitespace()
    {
        // <Trim>
        string source = "    I'm wider than I need to be.      ";

        // Each method returns a new string with whitespace removed.
        Console.WriteLine($"<{source.Trim()}>");
        // => <I'm wider than I need to be.>
        Console.WriteLine($"<{source.TrimStart()}>");
        // => <I'm wider than I need to be.      >
        Console.WriteLine($"<{source.TrimEnd()}>");
        // => <    I'm wider than I need to be.>
        // </Trim>
    }

    private static void RemoveText()
    {
        // <Remove>
        string source = "Many mountains are behind many clouds today.";
        string toRemove = "many ";

        // Find the text, then remove that span by index and length.
        int index = source.IndexOf(toRemove);
        string result = index >= 0
            ? source.Remove(index, toRemove.Length)
            : source;

        Console.WriteLine(result);
        // => Many mountains are behind clouds today.
        // </Remove>
    }

    private static void ReplaceWithRegex()
    {
        // <Regex>
        string source = "The mountains are still there behind the clouds today.";

        // Replace "the" or "The" followed by whitespace, preserving the original case.
        // The \s in the pattern keeps "there" from matching.
        string result = Regex.Replace(
            source,
            """the\s""",
            match => char.IsUpper(match.Value[0]) ? "Many " : "many ",
            RegexOptions.IgnoreCase);

        Console.WriteLine(result);
        // => Many mountains are still there behind many clouds today.
        // </Regex>
    }

    private static void ModifyCharacters()
    {
        // <CharArray>
        string phrase = "The quick brown fox jumps over the fence.";

        // A string is immutable, so copy it into a Span<char> to edit in place.
        Span<char> characters = stackalloc char[phrase.Length];
        phrase.CopyTo(characters);
        int index = phrase.IndexOf("fox");
        if (index != -1)
        {
            characters[index] = 'c';
            characters[index + 1] = 'a';
            characters[index + 2] = 't';
        }

        // Build a new string from the modified characters.
        string updated = new string(characters);
        Console.WriteLine(updated);
        // => The quick brown cat jumps over the fence.
        // </CharArray>
    }
}

Both overloads replace every match in the string, not just the first. Whether you pass a single character or a string, Replace substitutes all occurrences in one call.

Trim whitespace

Use System.String.Trim, System.String.TrimStart, and System.String.TrimEnd to remove leading or trailing whitespace. Each method returns a new string:

sample · csharpdocs/csharp/fundamentals/strings/common-tasks/snippets/modify/Program.csTrim

csharp
using System.Text.RegularExpressions;

namespace ModifyStrings;

public static class Program
{
    public static void Main()
    {
        ReplaceText();
        Console.WriteLine();
        ReplaceCharacters();
        Console.WriteLine();
        TrimWhitespace();
        Console.WriteLine();
        RemoveText();
        Console.WriteLine();
        ReplaceWithRegex();
        Console.WriteLine();
        ModifyCharacters();
    }

    private static void ReplaceText()
    {
        // <Replace>
        string source = "The mountains are behind the clouds today.";

        // Replace returns a new string; the original is unchanged.
        string updated = source.Replace("mountains", "peaks");

        Console.WriteLine(source);
        // => The mountains are behind the clouds today.
        Console.WriteLine(updated);
        // => The peaks are behind the clouds today.
        // </Replace>
    }

    private static void ReplaceCharacters()
    {
        // <ReplaceChar>
        string source = "The mountains are behind the clouds today.";

        // Replace every occurrence of one character with another.
        string updated = source.Replace(' ', '_');

        Console.WriteLine(updated);
        // => The_mountains_are_behind_the_clouds_today.
        // </ReplaceChar>
    }

    private static void TrimWhitespace()
    {
        // <Trim>
        string source = "    I'm wider than I need to be.      ";

        // Each method returns a new string with whitespace removed.
        Console.WriteLine($"<{source.Trim()}>");
        // => <I'm wider than I need to be.>
        Console.WriteLine($"<{source.TrimStart()}>");
        // => <I'm wider than I need to be.      >
        Console.WriteLine($"<{source.TrimEnd()}>");
        // => <    I'm wider than I need to be.>
        // </Trim>
    }

    private static void RemoveText()
    {
        // <Remove>
        string source = "Many mountains are behind many clouds today.";
        string toRemove = "many ";

        // Find the text, then remove that span by index and length.
        int index = source.IndexOf(toRemove);
        string result = index >= 0
            ? source.Remove(index, toRemove.Length)
            : source;

        Console.WriteLine(result);
        // => Many mountains are behind clouds today.
        // </Remove>
    }

    private static void ReplaceWithRegex()
    {
        // <Regex>
        string source = "The mountains are still there behind the clouds today.";

        // Replace "the" or "The" followed by whitespace, preserving the original case.
        // The \s in the pattern keeps "there" from matching.
        string result = Regex.Replace(
            source,
            """the\s""",
            match => char.IsUpper(match.Value[0]) ? "Many " : "many ",
            RegexOptions.IgnoreCase);

        Console.WriteLine(result);
        // => Many mountains are still there behind many clouds today.
        // </Regex>
    }

    private static void ModifyCharacters()
    {
        // <CharArray>
        string phrase = "The quick brown fox jumps over the fence.";

        // A string is immutable, so copy it into a Span<char> to edit in place.
        Span<char> characters = stackalloc char[phrase.Length];
        phrase.CopyTo(characters);
        int index = phrase.IndexOf("fox");
        if (index != -1)
        {
            characters[index] = 'c';
            characters[index + 1] = 'a';
            characters[index + 2] = 't';
        }

        // Build a new string from the modified characters.
        string updated = new string(characters);
        Console.WriteLine(updated);
        // => The quick brown cat jumps over the fence.
        // </CharArray>
    }
}

Remove a span of characters

The System.String.Remove method deletes a number of characters starting at an index. Combine it with System.String.IndexOf to locate the text to remove:

sample · csharpdocs/csharp/fundamentals/strings/common-tasks/snippets/modify/Program.csRemove

csharp
using System.Text.RegularExpressions;

namespace ModifyStrings;

public static class Program
{
    public static void Main()
    {
        ReplaceText();
        Console.WriteLine();
        ReplaceCharacters();
        Console.WriteLine();
        TrimWhitespace();
        Console.WriteLine();
        RemoveText();
        Console.WriteLine();
        ReplaceWithRegex();
        Console.WriteLine();
        ModifyCharacters();
    }

    private static void ReplaceText()
    {
        // <Replace>
        string source = "The mountains are behind the clouds today.";

        // Replace returns a new string; the original is unchanged.
        string updated = source.Replace("mountains", "peaks");

        Console.WriteLine(source);
        // => The mountains are behind the clouds today.
        Console.WriteLine(updated);
        // => The peaks are behind the clouds today.
        // </Replace>
    }

    private static void ReplaceCharacters()
    {
        // <ReplaceChar>
        string source = "The mountains are behind the clouds today.";

        // Replace every occurrence of one character with another.
        string updated = source.Replace(' ', '_');

        Console.WriteLine(updated);
        // => The_mountains_are_behind_the_clouds_today.
        // </ReplaceChar>
    }

    private static void TrimWhitespace()
    {
        // <Trim>
        string source = "    I'm wider than I need to be.      ";

        // Each method returns a new string with whitespace removed.
        Console.WriteLine($"<{source.Trim()}>");
        // => <I'm wider than I need to be.>
        Console.WriteLine($"<{source.TrimStart()}>");
        // => <I'm wider than I need to be.      >
        Console.WriteLine($"<{source.TrimEnd()}>");
        // => <    I'm wider than I need to be.>
        // </Trim>
    }

    private static void RemoveText()
    {
        // <Remove>
        string source = "Many mountains are behind many clouds today.";
        string toRemove = "many ";

        // Find the text, then remove that span by index and length.
        int index = source.IndexOf(toRemove);
        string result = index >= 0
            ? source.Remove(index, toRemove.Length)
            : source;

        Console.WriteLine(result);
        // => Many mountains are behind clouds today.
        // </Remove>
    }

    private static void ReplaceWithRegex()
    {
        // <Regex>
        string source = "The mountains are still there behind the clouds today.";

        // Replace "the" or "The" followed by whitespace, preserving the original case.
        // The \s in the pattern keeps "there" from matching.
        string result = Regex.Replace(
            source,
            """the\s""",
            match => char.IsUpper(match.Value[0]) ? "Many " : "many ",
            RegexOptions.IgnoreCase);

        Console.WriteLine(result);
        // => Many mountains are still there behind many clouds today.
        // </Regex>
    }

    private static void ModifyCharacters()
    {
        // <CharArray>
        string phrase = "The quick brown fox jumps over the fence.";

        // A string is immutable, so copy it into a Span<char> to edit in place.
        Span<char> characters = stackalloc char[phrase.Length];
        phrase.CopyTo(characters);
        int index = phrase.IndexOf("fox");
        if (index != -1)
        {
            characters[index] = 'c';
            characters[index + 1] = 'a';
            characters[index + 2] = 't';
        }

        // Build a new string from the modified characters.
        string updated = new string(characters);
        Console.WriteLine(updated);
        // => The quick brown cat jumps over the fence.
        // </CharArray>
    }
}

Replace text that matches a pattern

When you need to replace text that follows a pattern rather than an exact string, use regular expressions. The System.Text.RegularExpressions.Regex.Replace method accepts a function that computes each replacement, so you can preserve details such as the original capitalization. The pattern the\s matches "the" followed by a whitespace character, which prevents it from matching "there":

sample · csharpdocs/csharp/fundamentals/strings/common-tasks/snippets/modify/Program.csRegex

csharp
using System.Text.RegularExpressions;

namespace ModifyStrings;

public static class Program
{
    public static void Main()
    {
        ReplaceText();
        Console.WriteLine();
        ReplaceCharacters();
        Console.WriteLine();
        TrimWhitespace();
        Console.WriteLine();
        RemoveText();
        Console.WriteLine();
        ReplaceWithRegex();
        Console.WriteLine();
        ModifyCharacters();
    }

    private static void ReplaceText()
    {
        // <Replace>
        string source = "The mountains are behind the clouds today.";

        // Replace returns a new string; the original is unchanged.
        string updated = source.Replace("mountains", "peaks");

        Console.WriteLine(source);
        // => The mountains are behind the clouds today.
        Console.WriteLine(updated);
        // => The peaks are behind the clouds today.
        // </Replace>
    }

    private static void ReplaceCharacters()
    {
        // <ReplaceChar>
        string source = "The mountains are behind the clouds today.";

        // Replace every occurrence of one character with another.
        string updated = source.Replace(' ', '_');

        Console.WriteLine(updated);
        // => The_mountains_are_behind_the_clouds_today.
        // </ReplaceChar>
    }

    private static void TrimWhitespace()
    {
        // <Trim>
        string source = "    I'm wider than I need to be.      ";

        // Each method returns a new string with whitespace removed.
        Console.WriteLine($"<{source.Trim()}>");
        // => <I'm wider than I need to be.>
        Console.WriteLine($"<{source.TrimStart()}>");
        // => <I'm wider than I need to be.      >
        Console.WriteLine($"<{source.TrimEnd()}>");
        // => <    I'm wider than I need to be.>
        // </Trim>
    }

    private static void RemoveText()
    {
        // <Remove>
        string source = "Many mountains are behind many clouds today.";
        string toRemove = "many ";

        // Find the text, then remove that span by index and length.
        int index = source.IndexOf(toRemove);
        string result = index >= 0
            ? source.Remove(index, toRemove.Length)
            : source;

        Console.WriteLine(result);
        // => Many mountains are behind clouds today.
        // </Remove>
    }

    private static void ReplaceWithRegex()
    {
        // <Regex>
        string source = "The mountains are still there behind the clouds today.";

        // Replace "the" or "The" followed by whitespace, preserving the original case.
        // The \s in the pattern keeps "there" from matching.
        string result = Regex.Replace(
            source,
            """the\s""",
            match => char.IsUpper(match.Value[0]) ? "Many " : "many ",
            RegexOptions.IgnoreCase);

        Console.WriteLine(result);
        // => Many mountains are still there behind many clouds today.
        // </Regex>
    }

    private static void ModifyCharacters()
    {
        // <CharArray>
        string phrase = "The quick brown fox jumps over the fence.";

        // A string is immutable, so copy it into a Span<char> to edit in place.
        Span<char> characters = stackalloc char[phrase.Length];
        phrase.CopyTo(characters);
        int index = phrase.IndexOf("fox");
        if (index != -1)
        {
            characters[index] = 'c';
            characters[index + 1] = 'a';
            characters[index + 2] = 't';
        }

        // Build a new string from the modified characters.
        string updated = new string(characters);
        Console.WriteLine(updated);
        // => The quick brown cat jumps over the fence.
        // </CharArray>
    }
}

For pattern-based searching rather than replacement, see Search strings in C#. For the regular expression syntax, see Regular expression language quick reference.

Modify individual characters

To change characters by position, copy the string into a System.Span of characters, modify the span, and then build a new string from it. The following example finds the word "fox" and replaces it with "cat":

sample · csharpdocs/csharp/fundamentals/strings/common-tasks/snippets/modify/Program.csCharArray

csharp
using System.Text.RegularExpressions;

namespace ModifyStrings;

public static class Program
{
    public static void Main()
    {
        ReplaceText();
        Console.WriteLine();
        ReplaceCharacters();
        Console.WriteLine();
        TrimWhitespace();
        Console.WriteLine();
        RemoveText();
        Console.WriteLine();
        ReplaceWithRegex();
        Console.WriteLine();
        ModifyCharacters();
    }

    private static void ReplaceText()
    {
        // <Replace>
        string source = "The mountains are behind the clouds today.";

        // Replace returns a new string; the original is unchanged.
        string updated = source.Replace("mountains", "peaks");

        Console.WriteLine(source);
        // => The mountains are behind the clouds today.
        Console.WriteLine(updated);
        // => The peaks are behind the clouds today.
        // </Replace>
    }

    private static void ReplaceCharacters()
    {
        // <ReplaceChar>
        string source = "The mountains are behind the clouds today.";

        // Replace every occurrence of one character with another.
        string updated = source.Replace(' ', '_');

        Console.WriteLine(updated);
        // => The_mountains_are_behind_the_clouds_today.
        // </ReplaceChar>
    }

    private static void TrimWhitespace()
    {
        // <Trim>
        string source = "    I'm wider than I need to be.      ";

        // Each method returns a new string with whitespace removed.
        Console.WriteLine($"<{source.Trim()}>");
        // => <I'm wider than I need to be.>
        Console.WriteLine($"<{source.TrimStart()}>");
        // => <I'm wider than I need to be.      >
        Console.WriteLine($"<{source.TrimEnd()}>");
        // => <    I'm wider than I need to be.>
        // </Trim>
    }

    private static void RemoveText()
    {
        // <Remove>
        string source = "Many mountains are behind many clouds today.";
        string toRemove = "many ";

        // Find the text, then remove that span by index and length.
        int index = source.IndexOf(toRemove);
        string result = index >= 0
            ? source.Remove(index, toRemove.Length)
            : source;

        Console.WriteLine(result);
        // => Many mountains are behind clouds today.
        // </Remove>
    }

    private static void ReplaceWithRegex()
    {
        // <Regex>
        string source = "The mountains are still there behind the clouds today.";

        // Replace "the" or "The" followed by whitespace, preserving the original case.
        // The \s in the pattern keeps "there" from matching.
        string result = Regex.Replace(
            source,
            """the\s""",
            match => char.IsUpper(match.Value[0]) ? "Many " : "many ",
            RegexOptions.IgnoreCase);

        Console.WriteLine(result);
        // => Many mountains are still there behind many clouds today.
        // </Regex>
    }

    private static void ModifyCharacters()
    {
        // <CharArray>
        string phrase = "The quick brown fox jumps over the fence.";

        // A string is immutable, so copy it into a Span<char> to edit in place.
        Span<char> characters = stackalloc char[phrase.Length];
        phrase.CopyTo(characters);
        int index = phrase.IndexOf("fox");
        if (index != -1)
        {
            characters[index] = 'c';
            characters[index + 1] = 'a';
            characters[index + 2] = 't';
        }

        // Build a new string from the modified characters.
        string updated = new string(characters);
        Console.WriteLine(updated);
        // => The quick brown cat jumps over the fence.
        // </CharArray>
    }
}

For high-performance scenarios that avoid intermediate allocations, the runtime provides lower-level APIs such as System.String.Create. Those techniques are advanced; for everyday code, the methods in this article are the right choice.

See also