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:

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:
| Data | Values | Used in |
|---|---|---|
| Laptop prices (USD) | 899, 249, 1299, 549, 129 | Steps 1-2 |
| US cities | denver, Austin, boston, Chicago, El Paso | Step 3 |
| 2020 Census counts | California 39,538,223, Texas 29,145,505, Florida 21,538,187, Ohio 11,799,448 | Step 4, final |
| Store products | Desk 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

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

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

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

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

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?
| Goal | Use | Changes original? |
|---|---|---|
| Ascending, fastest | Array.Sort(arr) | Yes |
| Descending | Array.Sort(arr, (x, y) => y.CompareTo(x)) | Yes |
| Strings, ignore case | Array.Sort(arr, StringComparer.OrdinalIgnoreCase) | Yes |
| Objects by a property | Comparison lambda or IComparable<T> | Yes |
| Sorted copy, or ties keep order | OrderBy().ThenBy().ToArray() | No |
Where to Take It Next
- Print the ranking as one line with a comma-separated string.
- Look up a state’s population by name with a Dictionary in C# after sorting.
More array and collection tutorials worth a look:
- Check if a string array contains an element
- Dynamic arrays in C# when the size changes
- ArrayList in C# and why List<T> replaced it
- The for loop in C#, with index-based array examples
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.
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…