To remove a character from a string in C#, call Replace with the character as a string and an empty string as the replacement. It deletes every occurrence in one line:
string sku = "SKU-4471-BLK";
Console.WriteLine(sku.Replace("-", "")); // SKU4471BLK
Need only the first or last match instead? That’s Remove plus IndexOf. I ran each method below on .NET 10 with US phone numbers, SKUs and city names.
How Do You Remove a Character from a String in C#?
Pick the method by what you want gone. Here’s the cheat sheet I keep handy:
| Goal | Method | Example result |
|---|---|---|
| Every occurrence of one character | s.Replace("a", "") | Atlanta -> Atlnt |
| First occurrence | s.Remove(s.IndexOf(c), 1) | Tampa FL, 33602 |
| Last occurrence | s.Remove(s.LastIndexOf(c), 1) | Tampa, FL 33602 |
| Several different characters | Split + Concat, LINQ, StringBuilder | 4155550137 |
| A whole class (non-digits, vowels) | Regex.Replace | WH2207blk12 |
| Ignore upper/lower case | Replace(..., StringComparison.OrdinalIgnoreCase) | ississippi |
None of these change the original: a C# string is immutable, so each call returns a new string to assign. If you only want to cut characters off the end by position, remove the last character from a string with Remove or ranges instead.
Remove Every Occurrence of a Character with String.Replace
Same idea, run on “Atlanta” with three ways to write the empty replacement:
string city = "Atlanta";
string noA = city.Replace("a", "");
string viaChar = city.Replace('a'.ToString(), string.Empty);
string viaNull = city.Replace("a", null);
Console.WriteLine(noA);
Console.WriteLine(viaChar);
Console.WriteLine(viaNull);
Console.WriteLine(city);
Console.WriteLine(city.Replace('a', '*'));
string same = city.Replace("z", "");
Console.WriteLine(ReferenceEquals(city, same));
Output:
Atlnt
Atlnt
Atlnt
Atlanta
Atl*nt*
True

All three print “Atlnt”. The capital A survives because Replace is ordinal, which means case-sensitive. Passing null as the new value also removes matches, as Microsoft documents.
Replace('a', '*') shows the catch: the char overload swaps one character for another, and there’s no empty char, so you can’t delete with it. When nothing matches, you get the same instance back (True on the last line), so the call costs no allocation.
Remove the First or Last Occurrence with IndexOf, LastIndexOf and Remove
Remove(startIndex, count) deletes by position, so pair it with IndexOf or LastIndexOf to find the character first. Here’s a city, state and ZIP line with two commas:
string address = "Tampa, FL, 33602";
int first = address.IndexOf(',');
int last = address.LastIndexOf(',');
Console.WriteLine(address.Remove(first, 1));
Console.WriteLine(address.Remove(last, 1));
int missing = address.IndexOf('#');
string safe = missing >= 0 ? address.Remove(missing, 1) : address;
Console.WriteLine($"'#' at {missing}: {safe}");
try { address.Remove(missing, 1); }
catch (ArgumentOutOfRangeException ex) { Console.WriteLine(ex.GetType().Name); }
Output:
Tampa FL, 33602
Tampa, FL 33602
'#' at -1: Tampa, FL, 33602
ArgumentOutOfRangeException

The first line drops the comma after Tampa, the second drops the one before the ZIP. When the character isn’t there, IndexOf returns -1 and Remove(-1, 1) throws ArgumentOutOfRangeException.
That’s why the missing >= 0 check matters. It’s the same index logic you’d use to compare two strings character by character, and catching the exception with try-catch is only a fallback.
Remove Several Characters with Split, LINQ Where or StringBuilder
Phone numbers are the classic case: you want “(415) 555-0137” stored as plain digits. Four ways to strip the parentheses, space and dash:
using System.Text;
string phone = "(415) 555-0137";
char[] junk = ['(', ')', ' ', '-'];
string chained = phone.Replace("(", "").Replace(")", "")
.Replace(" ", "").Replace("-", "");
string split = string.Concat(phone.Split(junk));
string linq = string.Concat(phone.Where(char.IsDigit));
var sb = new StringBuilder(phone.Length);
foreach (char ch in phone)
if (Array.IndexOf(junk, ch) < 0) sb.Append(ch);
Console.WriteLine($"Replace x4: {chained}");
Console.WriteLine($"Split: {split}");
Console.WriteLine($"LINQ Where: {linq}");
Console.WriteLine($"StringBuilder: {sb}");
Output:
Replace x4: 4155550137
Split: 4155550137
LINQ Where: 4155550137
StringBuilder: 4155550137

Every line prints 4155550137. Chained Replace reads fine for two or three characters, but it builds a new string per call.
Split + string.Concat and LINQ Where each walk the text once. LINQ hands back an IEnumerable<char>, the same thing you’d get from a char array to string conversion.
The StringBuilder loop is the most code, but it’s the one I use on large text or in hot paths. The difference between string and StringBuilder explains why it avoids extra copies.
Remove a Class of Characters with Regex.Replace
When the rule is a category, like “anything that isn’t a digit”, a regular expression says it in one pattern. Same phone, plus a messy warehouse SKU:
using System.Text.RegularExpressions;
string phone = "(415) 555-0137";
string sku = "WH-2207/blk #12";
Console.WriteLine(Regex.Replace(phone, @"\D", ""));
Console.WriteLine(Regex.Replace(sku, "[^A-Za-z0-9]", ""));
Console.WriteLine(Regex.Replace("Orlando", "[aeiou]", ""));
Console.WriteLine(Regex.Replace("Orlando", "[aeiou]", "",
RegexOptions.IgnoreCase));
Output:
4155550137
WH2207blk12
Orlnd
rlnd
![VS Code running RegexRemove.cs: C# Regex.Replace with \D strips (415) 555-0137 to 4155550137 and [^A-Za-z0-9] cleans the SKU to WH2207blk12](https://aspdotnethelp.com/wp-content/uploads/2026/10/csharp-regex-replace-remove-non-digit-characters.png)
\D matches any non-digit, and [^A-Za-z0-9] removes everything except letters and numbers, so the SKU becomes WH2207blk12. [aeiou] leaves the capital O in “Orlando” until you add RegexOptions.IgnoreCase.
Regex is slower than Replace for one fixed character, so I keep it for patterns. To check that a character exists before removing it, see check if a string contains a character.
Remove a Character Ignoring Case with StringComparison
Plain Replace won’t touch the capital M in “Mississippi”. The StringComparison overload (.NET Core 2.0 and later) fixes that:
string state = "Mississippi";
Console.WriteLine(state.Replace("m", ""));
Console.WriteLine(state.Replace("m", "", StringComparison.OrdinalIgnoreCase));
string city = "Kansas City";
Console.WriteLine(city.Replace("k", "", StringComparison.OrdinalIgnoreCase));
Console.WriteLine(string.Concat(city.Where(ch => char.ToLowerInvariant(ch) != 's')));
Output:
Mississippi
ississippi
ansas City
Kana City

The first line comes back unchanged, the second drops the M. On “Kansas City” the LINQ version removes both lowercase s characters with char.ToLowerInvariant, which also works on .NET Framework, where this overload doesn’t exist.
Calling Replace on a null string throws NullReferenceException, so check if a string is null or empty before you strip anything. To drop a whole word rather than a character, remove the last word from a string works with the same index tricks.
A few more string tasks that use the same building blocks:
- Get the first N characters of a string
- Get the first character of each word
- Reverse a string in C#
- Compare a string with multiple values
Frequently Asked Questions
How do I remove a specific character from a string in C#?
Use text.Replace("x", ""). It returns a new string with every x removed. Assign the result, because the original string doesn’t change.
Why can’t I use Replace(‘a’, ”) to remove a char?
C# has no empty char literal, so '' doesn’t compile. Use the string overload, Replace("a", "") or Replace("a", string.Empty).
How do I remove only the first occurrence of a character?
Find it with IndexOf, check the result isn’t -1, then call text.Remove(index, 1). Use LastIndexOf for the last occurrence.
How do I remove all non-numeric characters from a string in C#?
Use Regex.Replace(text, @"\D", "") or string.Concat(text.Where(char.IsDigit)). Both turn “(415) 555-0137” into 4155550137.
Does String.Replace change the original string?
No. Strings are immutable, so Replace and Remove always return a new string. The String.Replace reference on Microsoft Learn lists every overload, including the StringComparison one.
Is Replace case-sensitive in C#?
Yes, it’s ordinal by default. Pass StringComparison.OrdinalIgnoreCase as the third argument (.NET Core 2.0+) to remove both upper and lowercase matches.
Bijay Kumar is a renowned software engineer, accomplished author, and distinguished Microsoft Most Valuable Professional (MVP) specializing in SharePoint. With a rich professional background spanning over 15 years, Bijay has established himself as an authority in the field of information technology. He possesses unparalleled expertise in multiple programming languages and technologies such as ASP.NET, ASP.NET MVC, C#.NET, and SharePoint, which has enabled him to develop innovative and cutting-edge solutions for clients across the globe. Read more…