C# Program to Reverse a String
"Reverse a string" is one of the most common coding questions in C# interviews, especially for freshers. The interviewer usually wants to see three things: that you know the quick built-in way, that you can write it without built-in methods, and that you understand why strings need special handling in .NET (they are immutable).
This article shows six working solutions with their real output, measures how fast each one is, and then covers the follow-up questions interviewers love: Unicode and emoji, reversing words, and palindromes. All output below comes from running the code on .NET 8.
Why you can't reverse a string "in place"
In C#, string is immutable: once created, its characters can never change. text[0] = 'X' doesn't even compile. So every solution has to build a new string. Usually that means copying the characters into a char[] array (which can be changed), reversing the array, and creating a new string from it.
The six solutions
using System.Text;
string input = "MakeMyCodes";
1. Array.Reverse (the usual answer)
static string ReverseWithArray(string s)
{
char[] chars = s.ToCharArray(); // copy the characters into an array
Array.Reverse(chars); // reverse the array in place
return new string(chars); // build a new string
}
2. Two pointers, without any built-in reverse method
This is what the interviewer means by "reverse a string without using built-in functions". Swap the first and last characters, then move both ends towards the middle:
static string ReverseInPlace(string s)
{
char[] c = s.ToCharArray();
int left = 0, right = c.Length - 1;
while (left < right)
{
(c[left], c[right]) = (c[right], c[left]); // swap using a tuple
left++;
right--;
}
return new string(c);
}
For "MakeMyCodes" (11 characters), it swaps positions 0↔10, 1↔9, 2↔8, 3↔7 and 4↔6; position 5 is the middle and stays. That's only n / 2 swaps.
3. Loop backwards with StringBuilder
static string ReverseWithLoop(string s)
{
var sb = new StringBuilder(s.Length); // pre-size the buffer
for (int i = s.Length - 1; i >= 0; i--)
sb.Append(s[i]);
return sb.ToString();
}
4. LINQ (one line)
string reversed = new string(input.Reverse().ToArray());
5. Recursion
static string ReverseRecursive(string s) =>
s.Length <= 1 ? s : ReverseRecursive(s.Substring(1)) + s[0];
Recursion is sometimes asked to test your understanding of it, but it creates a new string at every level and can overflow the stack for long inputs. Never use it in real code for this.
6. string.Create with Span (fastest)
static string ReverseWithCreate(string s) =>
string.Create(s.Length, s, (span, source) =>
{
source.AsSpan().CopyTo(span); // write the characters straight into the new string
span.Reverse(); // reverse them there: no extra array
});
string.Create lets you fill the new string's memory directly, so there is only one allocation: the result itself.
Output
Console.WriteLine($"1. Array.Reverse : {ReverseWithArray(input)}");
Console.WriteLine($"2. Loop : {ReverseWithLoop(input)}");
Console.WriteLine($"3. Two pointers : {ReverseInPlace(input)}");
Console.WriteLine($"4. LINQ : {new string(input.Reverse().ToArray())}");
Console.WriteLine($"5. Recursion : {ReverseRecursive(input)}");
Console.WriteLine($"6. string.Create : {ReverseWithCreate(input)}");
Which one is fastest?
We reversed a 10,003-character string thousands of times with each method (Release build, .NET 8, after a warm-up run):
- string.Create and Array.Reverse are the fastest: both use highly optimised (vectorised) code inside .NET.
- The hand-written two-pointer loop is correct and allocation-friendly, but about 5 times slower than the built-in reverse, which processes many characters per CPU instruction.
- LINQ is the slowest of the reasonable options because it goes through enumerators and a buffer.
- Building the result with
result += s[i]in a loop is a disaster: about 2,400 times slower than Array.Reverse. Each+=creates a brand-new string and copies everything built so far, so the work grows with the square of the length. Never concatenate strings in a loop; useStringBuilder.
The Unicode trap: emoji and accents
A C# char is one UTF-16 code unit, not always one visible character. An emoji like 👍 needs two chars (a "surrogate pair"), and "é" can be written as "e" plus a separate combining accent. Reversing chars breaks them:
using System.Globalization;
string tricky = "Café 👍";
Console.WriteLine($"Unicode input : {tricky} (Length = {tricky.Length})");
Console.WriteLine($"Array.Reverse : {ReverseWithArray(tricky)}");
Console.WriteLine($"Text elements : {ReverseTextElements(tricky)}");
// Reverse by visible characters ("text elements"), not by chars
static string ReverseTextElements(string s)
{
var parts = new List<string>();
TextElementEnumerator e = StringInfo.GetTextElementEnumerator(s);
while (e.MoveNext())
parts.Add(e.GetTextElement());
parts.Reverse();
return string.Concat(parts);
}
- "Café 👍" looks like 6 characters, but
Lengthis 7, because the emoji takes two chars. Array.Reverseswapped the two halves of the emoji, producing invalid text (shown as �).- Reversing by text elements (what a user sees as one character) keeps the emoji intact.
The same happens with a combining accent ("Café", which displays as "Café"): char reversal puts the accent at the start, on nothing, giving "́efaC", while text-element reversal correctly gives "éfaC". For names, chat messages or any user-entered text, use the text-element version. Mentioning this in an interview is a strong signal that you understand strings deeply.
Follow-up 1: reverse the words in a sentence
static string ReverseWords(string s) =>
string.Join(" ", s.Split(' ', StringSplitOptions.RemoveEmptyEntries).Reverse());
Console.WriteLine(ReverseWords("C# is fun to learn"));
RemoveEmptyEntries handles multiple spaces between words.
Follow-up 2: check for a palindrome
A palindrome reads the same forwards and backwards. Ignore case, spaces and punctuation, and compare from both ends (no need to build the reversed string at all):
static bool IsPalindrome(string s)
{
string clean = new string(s.Where(char.IsLetterOrDigit)
.Select(char.ToLowerInvariant)
.ToArray());
int left = 0, right = clean.Length - 1;
while (left < right)
if (clean[left++] != clean[right--])
return false;
return true;
}
foreach (var w in new[] { "Madam", "level", "Code", "A man, a plan, a canal: Panama" })
Console.WriteLine($"IsPalindrome(\"{w}\") = {IsPalindrome(w)}");
Comparison
| Method | Speed | Extra memory | Use it when |
|---|---|---|---|
Array.Reverse | Very fast | One char[] | Default choice in normal code |
string.Create + Span | Fastest | None beyond the result | Performance-critical code |
| Two pointers | Fast | One char[] | "Without built-in functions" questions |
| StringBuilder loop | Medium | Builder buffer | When you also transform characters while reversing |
| LINQ | Slow | Enumerator + buffer | Quick one-off scripts |
| Recursion | Slow | A new string per call | Only to demonstrate recursion |
+= in a loop | Extremely slow | A new string per character | Never |
| Text elements | Slower | A list of parts | User text with emoji or accents |
Interview questions
1. How do you reverse a string in C#?
Convert it to a char[] with ToCharArray(), call Array.Reverse, and create a new string: new string(chars). Strings are immutable, so you always build a new one.
2. How do you reverse a string without built-in methods?
Use two indexes, one at each end of a char[], swap the characters, and move the indexes towards the middle until they meet. It needs only n/2 swaps and no extra array besides the copy.
3. Why shouldn't you use += to build the reversed string?
Every += creates a new string and copies all previous characters, which makes the algorithm O(n²). In our test it was about 2,400 times slower than Array.Reverse for a 10,000-character string. Use StringBuilder or a char[].
4. Why can reversing a string break emoji?
Some characters, such as emoji, are stored as two UTF-16 chars (a surrogate pair), and accents can be separate combining characters. Reversing chars separates them. Use StringInfo text elements to reverse by visible characters.
5. Is string.Length the number of characters a user sees?
No. It is the number of UTF-16 code units. "Café 👍" has a Length of 7 but shows 6 characters; new StringInfo(s).LengthInTextElements gives the visible count.
Summary
- Strings are immutable, so reversing always creates a new string.
Array.Reverseon achar[]is the standard answer;string.Createis the fastest.- The two-pointer swap is the answer to "without built-in functions".
- Never build strings with
+=in a loop. - Use text elements (
StringInfo) to reverse user text with emoji or accents safely.