はじめに:「逆順ソート」は“優先度の高いものを先頭に持ってくる技”
業務システムでは「新しい順」「金額の大きい順」「重要度の高い順」のように、“大きいほう・新しいほうを先頭にしたい”場面がとても多いです。
これが「逆順ソート(降順ソート)」です。
C# では、
昇順用の OrderBy に対して、逆順用の OrderByDescending
並び替えたあとに順番だけひっくり返す Reverse
List 自体を書き換える Sort とカスタム比較
といった道具があります。
ここから、「どれをどう使うと読みやすくて安全か」を、初心者向けにかみ砕いていきます。
基本形:OrderByDescending で“大きいほうから並べる”
数値を大きい順に並べる
一番シンプルな例からいきます。
using System;
using System.Collections.Generic;
using System.Linq;
var numbers = new List<int> { 5, 2, 9, 1, 3 };
var desc = numbers.OrderByDescending(x => x);
foreach (var n in desc)
{
Console.WriteLine(n); // 9, 5, 3, 2, 1
}
C#OrderBy(x => x) が「小さい順(昇順)」なのに対して、OrderByDescending(x => x) は「大きい順(降順)」です。
ここでの重要ポイントは、「元の numbers は書き換わらない」ということです。OrderByDescending は“並び替えられた新しい列”を返すだけで、元の List はそのままです。
日付を「新しい順」に並べる
業務でよくあるのが、「日付の新しい順」です。
var dates = new List<DateTime>
{
new DateTime(2026, 2, 10),
new DateTime(2026, 1, 5),
new DateTime(2026, 3, 1),
};
var newestFirst = dates.OrderByDescending(d => d);
foreach (var d in newestFirst)
{
Console.WriteLine(d.ToString("yyyy-MM-dd"));
// 2026-03-01
// 2026-02-10
// 2026-01-05
}
C#「新しい順=値が大きい順」なので、OrderByDescending がそのまま使えます。
オブジェクトを「特定のプロパティ」で逆順ソートする
売上を「金額の大きい順」に並べる
クラスのリストを逆順ソートするのが、実務ではメインです。
public class Sale
{
public DateTime Date { get; set; }
public int Amount { get; set; } // 金額
public string Customer { get; set; } = "";
}
C#データを用意します。
var sales = new List<Sale>
{
new Sale { Date = new DateTime(2026, 2, 10), Amount = 1000, Customer = "A" },
new Sale { Date = new DateTime(2026, 2, 11), Amount = 5000, Customer = "B" },
new Sale { Date = new DateTime(2026, 2, 12), Amount = 3000, Customer = "C" },
};
C#金額の大きい順に並べたいときは、こう書きます。
var byAmountDesc = sales
.OrderByDescending(s => s.Amount);
foreach (var s in byAmountDesc)
{
Console.WriteLine($"{s.Amount}: {s.Customer}");
// 5000: B
// 3000: C
// 1000: A
}
C#ここでの重要ポイントは、「OrderByDescending の中で“何を基準に逆順にするか”を選ぶ」ということです。s => s.Amount なら「金額の大きい順」、s => s.Date なら「日付の新しい順」になります。
複数キーでの逆順ソート:ThenBy / ThenByDescending の組み合わせ
「日付の新しい順 → 同じ日付なら金額の大きい順」
よくある要件として、「まず日付の新しい順、その中では金額の大きい順」というような複数条件ソートがあります。
var sorted = sales
.OrderByDescending(s => s.Date) // 日付の新しい順
.ThenByDescending(s => s.Amount); // 同じ日付内では金額の大きい順
C#OrderByDescending が“第一キー”、ThenByDescending が“第二キー”です。
もし「日付は新しい順、同じ日付内では金額の小さい順」にしたいなら、こうです。
var sorted = sales
.OrderByDescending(s => s.Date)
.ThenBy(s => s.Amount); // 第二キーだけ昇順
C#ここでの重要ポイントは、「昇順・降順をキーごとに選べる」ということです。OrderBy / OrderByDescending と ThenBy / ThenByDescending を組み合わせて、
“優先順位付きの並び順”を素直に表現できます。
Reverse と逆順ソートの違い
Reverse は「今の順番をひっくり返すだけ」
Reverse() というメソッドもありますが、これは「ソート」ではありません。
「今の順番をそのまま逆にする」だけです。
var numbers = new List<int> { 5, 2, 9 };
var reversed = numbers.AsEnumerable().Reverse();
foreach (var n in reversed)
{
Console.WriteLine(n); // 9, 2, 5
}
C#元の順番が「5, 2, 9」なので、その逆が「9, 2, 5」です。
値の大小は一切見ていません。
一方、OrderByDescending(x => x) は「値が大きい順」に並べます。
元の順番がどうであれ、「1, 2, 3, 5, 9」のように“ソートされた状態”になります。
ここでの重要ポイントは、「逆順ソートしたいときは OrderByDescending、単に今の順番をひっくり返したいだけなら Reverse」という使い分けです。
List<T>.Sort で“破壊的に逆順ソート”する
元の List 自体を書き換えてよい場合
LINQ の OrderByDescending は「新しい列を返す」方式でしたが、List<T> の Sort を使うと、「その List 自体を並べ替える」ことができます。
var numbers = new List<int> { 5, 2, 9, 1, 3 };
// 昇順ソート
numbers.Sort();
// 逆順にしたいときは Reverse を組み合わせる
numbers.Reverse();
foreach (var n in numbers)
{
Console.WriteLine(n); // 9, 5, 3, 2, 1
}
C#あるいは、比較関数で最初から逆順にしても構いません。
numbers.Sort((x, y) => y.CompareTo(x)); // y と x を逆にすることで降順
C#ここでの重要ポイントは、「Sort は元の List を壊す(順番を変える)」ということです。
元の順番が必要な場面では、Sort ではなく OrderByDescending を使うほうが安全です。
実務で意識してほしいこと
「何を基準に」「どちら向きに」並べたいかを言葉にする
逆順ソートを書く前に、まず日本語で整理してみてください。
日付の新しい順にしたいのか
金額の大きい順にしたいのか
優先度の高い順にしたいのか
それが決まれば、コードはほぼ自動的に決まります。
日付の新しい順 → OrderByDescending(x => x.Date)
金額の大きい順 → OrderByDescending(x => x.Amount)
という具合です。
「逆順ソート」と「単なる Reverse」を混同しない
「逆順ソート」は“値の大小を見て並べ替える”ことで、
「Reverse」は“今の順番をひっくり返すだけ”です。
すでに昇順ソート済みの List を「降順にしたい」だけなら、Sort → Reverse の組み合わせでもよいですが、
最初から並び順を決めるなら、OrderByDescending を素直に使うほうが意図が伝わりやすいです。
まとめ:「逆順ソートユーティリティ」は“重要なものを先頭に持ってくるためのレバー”
逆順ソートのポイントを短くまとめると、こうなります。
昇順は OrderBy、逆順は OrderByDescending。
複数キーの逆順ソートは、OrderByDescending と ThenBy / ThenByDescending の組み合わせで書く。Reverse は「今の順番をひっくり返すだけ」で、ソートとは別物。List<T>.Sort は List 自体を書き換えるので、元の順番が不要なときに使う。
この感覚が身につくと、「なんとなく並んでいる一覧」から卒業して、
“業務の意味に沿った順番でデータを並べる”コードが自然に書けるようになります。
