How to Sort an Array in C# (Ascending, Descending, Objects, LINQ)

The first thing most people type to sort an array in C# is var sorted = Array.Sort(prices);, and the compiler stops right there:

int[] prices = [899, 249, 1299, 549, 129];
var sorted = Array.Sort(prices);
// error CS0815: Cannot assign void to an implicitly-typed variable

Array.Sort sorts the array you pass in place and returns void, so call it on its own line and keep using prices. We’ll build a state population ranking on .NET 10, one sorting skill per step. Here’s what we’re building:

Sort an array in C# example in VS Code: six State records sorted by 2020 Census population, California 39,538,223 first and Ohio 11,799,448 last, plus an A-Z list of names
The finished ranking: Array.Sort with a Comparison lambda, then Order() for the A-Z list

Before You Start Sorting Arrays in C#

You need the .NET 10 SDK and VS Code; each step runs with dotnet run File.cs. New to the [...] syntax? My C# arrays guide covers it. Your sample data:

DataValuesUsed in
Laptop prices (USD)899, 249, 1299, 549, 129Steps 1-2
US citiesdenver, Austin, boston, Chicago, El PasoStep 3
2020 Census countsCalifornia 39,538,223, Texas 29,145,505, Florida 21,538,187, Ohio 11,799,448Step 4, final
Store productsDesk Lamp $39.50, Coffee Mug $12.99, …Step 5

Step 1: Sort an Array in Ascending Order with Array.Sort

Pass the array to Array.Sort, then print the same variable. Important: there’s no return value to catch.

int[] prices = [899, 249, 1299, 549, 129];   // laptop prices, USD

Console.WriteLine($"Before: {string.Join(", ", prices)}");

Array.Sort(prices);   // sorts the same array, returns void

Console.WriteLine($"After:  {string.Join(", ", prices)}");

Output:

Before: 899, 249, 1299, 549, 129
After:  129, 249, 549, 899, 1299
Array.Sort in C# sorting an int array of laptop prices in place in VS Code: 899, 249, 1299, 549, 129 becomes 129, 249, 549, 899, 1299
Array.Sort changes the original array and returns nothing

It’s an O(n log n) introsort that works on any IComparable type. Got a List<int> instead? Call list.Sort(), covered in my List in C# tutorial.

Checkpoint: After: 129, 249, 549, 899, 1299.

Step 2: Sort an Array in Descending Order

There’s no descending flag, so you pick one of three ways, each on a fresh copy of your prices:

int[] prices = [899, 249, 1299, 549, 129];

int[] a = [.. prices];
Array.Sort(a);
Array.Reverse(a);                          // 1: sort, then reverse
Console.WriteLine($"Sort + Reverse: {string.Join(", ", a)}");

int[] b = [.. prices];
Array.Sort(b, (x, y) => y.CompareTo(x));   // 2: Comparison<int>
Console.WriteLine($"Comparison:     {string.Join(", ", b)}");

int[] c = [.. prices];
var desc = Comparer<int>.Create((x, y) => y.CompareTo(x));
Array.Sort(c, desc);                       // 3: IComparer<int>
Console.WriteLine($"IComparer:      {string.Join(", ", c)}");

Output:

Sort + Reverse: 1299, 899, 549, 249, 129
Comparison:     1299, 899, 549, 249, 129
IComparer:      1299, 899, 549, 249, 129
C# sort array descending three ways in VS Code: Array.Sort plus Array.Reverse, a Comparison lambda and Comparer<int>.Create all print 1299, 899, 549, 249, 129
Three ways to sort descending, one result

Way 1 flips the ascending result with Array.Reverse; my guide to reverse an array in C# explains that call. Ways 2 and 3 swap x and y in one pass. I use the lambda, a Comparison<T> delegate (see delegates in C#).

Checkpoint: all three lines read 1299, 899, 549, 249, 129.

Step 3: Sort a String Array Alphabetically (Ordinal vs Culture)

With strings, case matters to some comparers and not to others:

using System.Globalization;
CultureInfo.CurrentCulture = new CultureInfo("en-US");

string[] cities = ["denver", "Austin", "boston", "Chicago", "El Paso"];

Array.Sort(cities);                              // culture-aware
Console.WriteLine($"Default:           {string.Join(", ", cities)}");

Array.Sort(cities, StringComparer.Ordinal);      // char codes: A-Z first
Console.WriteLine($"Ordinal:           {string.Join(", ", cities)}");

Array.Sort(cities, StringComparer.OrdinalIgnoreCase);
Console.WriteLine($"OrdinalIgnoreCase: {string.Join(", ", cities)}");

Output:

Default:           Austin, boston, Chicago, denver, El Paso
Ordinal:           Austin, Chicago, El Paso, boston, denver
OrdinalIgnoreCase: Austin, boston, Chicago, denver, El Paso
Sort a string array in C# in VS Code: the default culture sort and StringComparer.OrdinalIgnoreCase give Austin, boston, Chicago, denver, El Paso while StringComparer.Ordinal puts uppercase names first
Ordinal sorts by character code, so capital letters come first

The default comparer uses the current culture, which line 2 sets to en-US. StringComparer.Ordinal compares raw character codes, so El Paso lands before boston.

For keys and IDs, I’d pick StringComparer.OrdinalIgnoreCase: fast and the same on every machine. It’s also handy when you compare a string with multiple values.

Checkpoint: the Ordinal line ends with boston, denver.

Step 4: Sort an Array of Objects by a Property

Records can’t compare themselves, so you pass a lambda or implement IComparable<T>:

State[] states =
[
    new("Texas", 29_145_505), new("Ohio", 11_799_448),
    new("California", 39_538_223), new("Florida", 21_538_187),
];

Array.Sort(states, (a, b) => a.Population.CompareTo(b.Population));
Console.WriteLine($"By population: {string.Join(", ", states.Select(s => s.Name))}");

Array.Sort(states);   // uses CompareTo below: by name
Console.WriteLine($"By name:       {string.Join(", ", states.Select(s => s.Name))}");

record State(string Name, int Population) : IComparable<State>
{
    public int CompareTo(State? other) => string.CompareOrdinal(Name, other?.Name);
}

Output:

By population: Ohio, Florida, Texas, California
By name:       California, Florida, Ohio, Texas
C# sort an array of objects by property in VS Code: a Comparison lambda sorts State records by population, then Array.Sort uses IComparable to sort them by name
A lambda for one-off sorts, IComparable for the type’s natural order

Use the lambda for a one-off order. IComparable<State> gives the type a default order for plain Array.Sort(states); see interface in C#.

Checkpoint: By population: Ohio, Florida, Texas, California.

Step 5: Get a Sorted Copy with LINQ OrderBy and ThenBy

When you need to keep the original order, LINQ builds a new sequence instead:

using System.Globalization;
CultureInfo.CurrentCulture = new CultureInfo("en-US");

Product[] products =
[
    new("Desk Lamp", "Home", 39.50m), new("Coffee Mug", "Kitchen", 12.99m),
    new("Throw Pillow", "Home", 24.00m), new("Chef Knife", "Kitchen", 89.95m),
    new("Area Rug", "Home", 149.00m),
];

var sorted = products.OrderBy(p => p.Category).ThenByDescending(p => p.Price).ToArray();
foreach (var p in sorted) Console.WriteLine($"{p.Category,-8}{p.Name,-13}{p.Price,8:C}");
Console.WriteLine($"Original first item: {products[0].Name}");

record Product(string Name, string Category, decimal Price);

Output:

Home    Area Rug      $149.00
Home    Desk Lamp      $39.50
Home    Throw Pillow   $24.00
Kitchen Chef Knife     $89.95
Kitchen Coffee Mug     $12.99
Original first item: Desk Lamp
C# LINQ OrderBy and ThenByDescending sorting products by category then price into a new array in VS Code, while the original array still starts with Desk Lamp
LINQ returns a new array; the original order survives

ThenByDescending breaks ties per category. For plain values, .NET 7+ adds Order() and OrderDescending(), no key selector needed. Nothing sorts until ToArray() or a foreach loop in C# enumerates it.

Checkpoint: Original first item: Desk Lamp.

Test the Finished State Ranking Sort

Here’s the program from the top: Step 4’s lambda, flipped to descending, plus Order() for the A-Z line:

using System.Globalization;
CultureInfo.CurrentCulture = new CultureInfo("en-US");

State[] states =
[
    new("Texas", 29_145_505), new("Ohio", 11_799_448),
    new("California", 39_538_223), new("Florida", 21_538_187),
    new("New York", 20_201_249), new("Illinois", 12_812_508),
];

Array.Sort(states, (a, b) => b.Population.CompareTo(a.Population));
for (int i = 0; i < states.Length; i++)
    Console.WriteLine($"{i + 1}. {states[i].Name,-11}{states[i].Population,12:N0}");

string[] names = [.. states.Select(s => s.Name).Order()];
Console.WriteLine($"A-Z: {string.Join(", ", names)}");

record State(string Name, int Population);

Output:

1. California   39,538,223
2. Texas        29,145,505
3. Florida      21,538,187
4. New York     20,201,249
5. Illinois     12,812,508
6. Ohio         11,799,448
A-Z: California, Florida, Illinois, New York, Ohio, Texas

California leads with 39,538,223 and Ohio trails at 11,799,448. Set en-US for N0, or you’ll get another culture’s grouping; see how to format numbers with commas.

Sort Part of an Array or Two Parallel Arrays

Array.Sort(array, index, length) sorts a slice and leaves the rest alone:

int[] scores = [88, 72, 95, 60, 81, 99];

Array.Sort(scores, 1, 4);   // start at index 1, sort 4 elements

Console.WriteLine(string.Join(", ", scores));

Output:

88, 60, 72, 81, 95, 99

Only indexes 1-4 moved; 88 and 99 stayed put. When names and numbers live in two arrays, Array.Sort(keys, items) sorts the keys and drags each item along:

int[] populations = [29_145_505, 11_799_448, 39_538_223, 21_538_187];
string[] states = ["Texas", "Ohio", "California", "Florida"];

Array.Sort(populations, states);   // sorts keys, items follow

for (int i = 0; i < states.Length; i++)
    Console.WriteLine($"{states[i]}: {populations[i]}");

Output:

Ohio: 11799448
Florida: 21538187
Texas: 29145505
California: 39538223

Keys longer than items throws ArgumentException. In new code, I’d keep pairs in a record or a tuple in C#.

Is Array.Sort Stable in C#?

No. Microsoft documents Array.Sort as unstable, so equal elements can swap places, while OrderBy is stable.

Small ranges (16 elements or fewer) use insertion sort, which hides the problem, so this test uses 40 orders:

// 40 orders (ids 1-40) with priority 0-2, so most priorities are ties
var orders = Enumerable.Range(1, 40).Select(id => (Id: id, Priority: id % 3)).ToArray();

var linq = orders.OrderBy(o => o.Priority).ToArray();
var copy = orders.ToArray();
Array.Sort(copy, (x, y) => x.Priority.CompareTo(y.Priority));

Console.WriteLine($"OrderBy kept tie order:    {KeptOrder(linq)}");
Console.WriteLine($"Array.Sort kept tie order: {KeptOrder(copy)}");

static bool KeptOrder((int Id, int Priority)[] a) =>
    a.Zip(a.Skip(1)).All(p => p.First.Priority != p.Second.Priority || p.First.Id < p.Second.Id);

Output:

OrderBy kept tie order:    True
Array.Sort kept tie order: False

If your ties must keep their order, use OrderBy or add a tiebreaker (the ID) to the comparison.

Troubleshooting Array Sort Errors

CS0815 / nothing sorted: Array.Sort returns void. Call it as a statement, or use OrderBy(...).ToArray() if you want a result.

InvalidOperationException: the elements can’t be compared. Wrap the call in a try-catch block to see it, then pass a comparison:

Product[] items = [new("Desk Lamp", 39.50m), new("Coffee Mug", 12.99m)];

try { Array.Sort(items); }
catch (InvalidOperationException ex) { Console.WriteLine(ex.Message); }

Array.Sort(items, (x, y) => x.Price.CompareTo(y.Price));   // the fix
Console.WriteLine(items[0].Name);

record Product(string Name, decimal Price);

Output:

Failed to compare two elements in the array.
Coffee Mug

Which Array Sort Method Should You Pick?

GoalUseChanges original?
Ascending, fastestArray.Sort(arr)Yes
DescendingArray.Sort(arr, (x, y) => y.CompareTo(x))Yes
Strings, ignore caseArray.Sort(arr, StringComparer.OrdinalIgnoreCase)Yes
Objects by a propertyComparison lambda or IComparable<T>Yes
Sorted copy, or ties keep orderOrderBy().ThenBy().ToArray()No

Where to Take It Next

More array and collection tutorials worth a look:

Frequently Asked Questions

Does Array.Sort return a new array in C#?

No. It sorts the array in place and returns void, which is why var sorted = Array.Sort(arr) fails with CS0815. Use arr.Order().ToArray() for a sorted copy.

How do I sort an array in descending order in C#?

Use Array.Sort(arr, (x, y) => y.CompareTo(x)), or sort ascending and call Array.Reverse(arr). For a new array, use OrderDescending() on .NET 7+.

How do I sort a string array alphabetically, ignoring case?

Pass StringComparer.OrdinalIgnoreCase: Array.Sort(names, StringComparer.OrdinalIgnoreCase). Plain StringComparer.Ordinal puts every capitalized word first.

Is Array.Sort faster than LINQ OrderBy?

Usually, since it sorts in place without allocating. OrderBy copies, but it’s stable.

Is Array.Sort a stable sort?

No, equal elements may change order. Microsoft’s Array.Sort reference calls it an unstable introspective sort; OrderBy is stable.