How to Reverse an Array in C#: Array.Reverse and LINQ
Choose between Array.Reverse and LINQ Reverse().ToArray(), understand deferred execution and copying, and run a complete C# example.
Arrays hold fixed-size batches of values, represent data returned by APIs, and often sit at the boundary between application code and a library. When the required order changes, the right way to reverse an array in C# depends on one practical question: should the existing array change, or should the program receive a separate reversed result?
For an in-place change, use Array.Reverse. For a non-destructive result, use LINQ’s Reverse().ToArray(). Both produce the opposite order, but they have different return types, memory behavior, and timing. This guide uses ordinary one-dimensional zero-based arrays such as int[] and string[].
The short examples are independent snippets to place inside a method. Put using System;, using System.Linq;, and, for the list examples, using System.Collections.Generic; at the top of the file. A complete console program with its required imports appears near the end.
The shortest answer: call Array.Reverse
The framework method for changing an array in place is simple:
int[] values = { 1, 2, 3, 4, 5 };
Array.Reverse(values);
// values is now { 5, 4, 3, 2, 1 }
Array.Reverse(values) returns void, not a new array. An assignment such as int[] reversed = Array.Reverse(values) does not compile. Call the method as a statement, then use the existing array.
The reference named values still points to the same array object; its elements have been rearranged. Microsoft documents Array.Reverse as reversing the sequence in a one-dimensional array. Its generic overloads work naturally with typed arrays such as int[] and string[].
The operation takes linear time, O(n), while the ordinary swap-based implementation uses constant extra space, O(1). It is a direct choice when mutation is intended, not a universal performance winner for every surrounding application. The important ownership consequence is that every alias of the same array observes the new order.
Reversing is not sorting. Starting with { 3, 1, 2 } produces { 2, 1, 3 }, not descending { 3, 2, 1 }. Use sorting when a comparison rule should determine the result; use reversal when the existing sequence should simply run backward.
What Array.Reverse changes
Consider two variables referring to one array:
int[] original = { 10, 20, 30 };
int[] alias = original;
Array.Reverse(original);
// alias is also { 30, 20, 10 }
alias is not a copy. It is another reference to the same storage. That behavior is useful when a buffer is intentionally owned and updated, but surprising when the array came from a caller or is reused by several parts of a program. If the original order is part of the contract, make a copy first or use LINQ.
Reversing an empty array or a one-element array leaves it unchanged. Duplicate and negative values move like any other values. Passing null throws ArgumentNullException; it is a contract failure, not a request to silently do nothing. Decide explicitly whether your own helper rejects null input or handles it according to a documented policy.
A multidimensional array is not an ordinary one-dimensional T[]. The non-generic array API throws RankException for a multidimensional array. A rectangular int[,] therefore needs a separate decision about reversing rows, columns, or some other interpretation of its data.
Reverse only a portion with index and length
The indexed overload accepts a starting index and a length:
int[] values = { 0, 1, 2, 3, 4 };
Array.Reverse(values, 1, 3);
// values is now { 0, 3, 2, 1, 4 }
The third argument, 3, is a count, not an ending index. Here the affected positions are 1, 2, and 3. Remembering “start plus count” avoids a common off-by-one error when a requirement describes a final position instead of a length.
The overload validates the range. A negative index, negative length, or combination extending beyond the array causes an argument-related exception. A null array still causes ArgumentNullException. Validate boundaries derived from user input before the call instead of assuming every supplied count is valid. The same start-and-count convention appears on List<T>.Reverse.
Keep the original with LINQ Reverse and ToArray
When source order must survive, materialize a reversed LINQ sequence:
int[] values = { 1, 2, 3, 4, 5 };
int[] reversed = values.Reverse().ToArray();
// values is still { 1, 2, 3, 4, 5 }
// reversed is { 5, 4, 3, 2, 1 }
An array does not have an instance Reverse method. With using System.Linq;, the compiler selects the Enumerable.Reverse extension method. Microsoft describes Enumerable.Reverse as returning a sequence whose elements appear in reverse order. Calling ToArray forces immediate evaluation and stores the query results in an array.
This choice allocates storage for a new array. Reverse enumeration normally needs buffering rather than O(1)-memory streaming, although implementations may optimize particular source types. The useful guarantee is a separately materialized sequence, not a promise about the exact number of internal allocations on every .NET version.
Later changes to source positions do not rearrange the materialized result. However, ToArray copies the sequence container, not the objects referenced by its elements. In a string[], string references are copied; the strings are immutable. For mutable reference-type elements, both arrays can still point to the same underlying objects.
Deferred execution: when does LINQ read the array?
Reverse() alone returns an IEnumerable<T> query, not an immediate array. Enumeration happens later. That timing matters when the source is mutable:
int[] values = { 1, 2, 3 };
IEnumerable<int> query = values.Reverse();
values[0] = 99;
int[] result = query.ToArray();
// result is { 3, 2, 99 }
The change occurs before enumeration, so the query sees 99, not the earlier 1. Calling ToArray() when the query is created captures the reversed sequence at that earlier point. Holding the query for later does not freeze the original values.
This distinction matters when a helper returns IEnumerable<T> while its caller continues editing the source. Choose a materialization boundary deliberately when predictable captured order is required. Avoid modifying the source while it is being enumerated; deferred execution is not a synchronization mechanism or a guarantee of thread safety.
The List<T>.Reverse shadowing trap
A List<T> already has an instance Reverse() method. It reverses that list in place and returns void. The instance member takes precedence over the LINQ extension:
List<int> numbers = new List<int> { 1, 2, 3 };
numbers.Reverse(); // Changes numbers; returns void.
For a non-mutating LINQ pipeline, select the intended method explicitly:
List<int> numbers = new List<int> { 1, 2, 3 };
int[] reversed = numbers.AsEnumerable().Reverse().ToArray();
// Alternative: Enumerable.Reverse(numbers).ToArray()
Both forms select Enumerable.Reverse and leave the list order intact. AsEnumerable is convenient for fluent syntax; the static method call makes selection particularly obvious. Microsoft documents List<T>.Reverse as an O(n), in-place operation using Array.Reverse internally.
This explains why moving similar-looking code from an array to a list can change its meaning. Do not assume every .Reverse() call returns a query. Check the receiver’s type and whether an instance method is applicable before diagnosing the problem as a missing LINQ import.
Copy first, then reverse an independent array
A concise alternative is to clone the typed array and mutate the clone:
int[] source = { 1, 2, 3 };
int[] copy = (int[])source.Clone();
Array.Reverse(copy);
Array.Clone returns object, so this assignment needs the cast to int[]. Microsoft defines it as a shallow copy. Integers are copied as values, and changing a position in copy does not change that position in source.
For an array of mutable objects, the new array contains the same object references. Reversing its positions does not clone each object. Reverse().ToArray() has the same reference-element caveat. If the objects themselves must be independent, choose a deep-copy strategy separately; simply creating a second array cannot establish that guarantee.
A manual two-index loop when you need control
Move one index inward from each end and swap until the indexes meet:
for (int left = 0, right = values.Length - 1; left < right; left++, right--)
{
int temporary = values[left];
values[left] = values[right];
values[right] = temporary;
}
The indexes are signed integers. For an empty array, right is -1 and the condition fails immediately. For an odd-length array, the middle value stays in place. The temporary variable preserves one value while the other is moved into its position.
This is useful for teaching or specialized indexed storage, but Array.Reverse usually expresses intent better for ordinary arrays. A hand-written loop still mutates the source, so it does not solve aliasing or ownership by itself. If you only need backward output, a signed loop from values.Length - 1 down to zero can read each element without swapping anything.
Arrays, rows, strings, and text boundaries
For a jagged array such as int[][], reversing the outer array changes row order, not the elements inside each row. Reverse each row separately if that transformation is also required, and decide how to handle any null rows. Rectangular two-dimensional arrays require an explicit row or column policy rather than a call treating them as a one-dimensional array.
Reversing a char[] is not automatically safe human-readable text reversal. A C# char is a UTF-16 code unit; a supplementary character can use a surrogate pair, and a visible grapheme can contain multiple code points. Reversing code units can break those boundaries. See reversing a string in C# for string-specific methods.
An array of whole words is different: reversing its element positions preserves each string’s spelling. For that transformation, see reversing words without scrambling their letters. Decide what one element represents before choosing a reversal algorithm.
Run a complete example and choose your approach
With a .NET SDK installed, create a console project:
dotnet new console -n ReverseArrayDemo
Replace the generated ReverseArrayDemo/Program.cs contents with this complete program; do not append it beneath the generated top-level statement:
using System;
using System.Linq;
class Program
{
static void Main()
{
int[] values = { 1, 2, 3, 4, 5 };
Console.WriteLine("Original: " + string.Join(", ", values));
Array.Reverse(values);
Console.WriteLine("In place: " + string.Join(", ", values));
int[] source = { 1, 2, 3, 4, 5 };
int[] reversed = source.Reverse().ToArray();
Console.WriteLine("Source: " + string.Join(", ", source));
Console.WriteLine("LINQ copy: " + string.Join(", ", reversed));
int[] deferredSource = { 1, 2, 3 };
var deferred = deferredSource.Reverse();
deferredSource[0] = 99;
Console.WriteLine("Deferred: " + string.Join(", ", deferred.ToArray()));
int[] range = { 0, 1, 2, 3, 4 };
Array.Reverse(range, 1, 3);
Console.WriteLine("Range: " + string.Join(", ", range));
int[] clone = (int[])source.Clone();
Array.Reverse(clone);
Console.WriteLine("Clone reversed: " + string.Join(", ", clone));
}
}
Run it from the parent folder:
dotnet run --project ReverseArrayDemo
Expected output:
Original: 1, 2, 3, 4, 5
In place: 5, 4, 3, 2, 1
Source: 1, 2, 3, 4, 5
LINQ copy: 5, 4, 3, 2, 1
Deferred: 3, 2, 99
Range: 0, 3, 2, 1, 4
Clone reversed: 5, 4, 3, 2, 1
The program’s basic C# syntax and reversal results were also validated using Mono 6.8. The commands above use the .NET SDK workflow; they require that SDK to be available in your terminal.
Which method should you use?
Choose Array.Reverse(array) when the existing array should change and all aliases may observe the change. Choose array.Reverse().ToArray() for a separate materialized result without changing the source order. Keep array.Reverse() as a deferred query only when its evaluation timing is intentional. Clone first when explicitly separating copying from mutation makes the contract clearer.
Document that decision at the method boundary. A helper that reverses a caller-owned buffer should say it mutates the supplied array. A helper returning a new array should distinguish independent array positions from independent referenced objects. These small details prevent callers from guessing whether another clone is necessary. For one-off text transformations rather than C# container operations, visit the Text Reverser tool.
Try the Text Reverser tool
Reverse text, words, or letters instantly — free and entirely in your browser.
Open the tool