C#のSort完全ガイド|List・配列の昇順/降順ソートから独自条件の並び替えまで

はじめに

C#でデータを扱う際、要素を昇順や降順に並び替える「ソート」は非常に頻繁に使われる処理です。数値や文字列、日付などの基本的なソートから、独自の条件で並び替えるカスタムソートまで、C#には多彩な方法が用意されています。本記事では、Listや配列、LINQを使ったソート方法を網羅的に解説し、実務で役立つテクニックまで紹介します。

1. C#のSortでできること|まず押さえるべき並び替えの基本

1-1. C#におけるSortとは何か

C#のSortは、コレクション内の要素を特定の順序に並び替えるメソッドです。既存のデータ構造を直接書き換える「破壊的ソート」と呼ばれる特徴があります。Listや配列、LINQのOrderByなど、目的に応じて使い分けることが可能です。

1-2. 昇順ソートと降順ソートの違い

  • 昇順ソート:小さい値から大きい値、アルファベット順ならA→Z、日付なら古い順。

  • 降順ソート:大きい値から小さい値、Z→A、日付なら新しい順。

ソート方法の選択は、データの並べ替え目的に応じて決めます。

1-3. List・配列・LINQで使うソート方法の違い

  • List<T>.Sort():リストを破壊的に並び替え。

  • Array.Sort():配列の要素を破壊的に並び替え。

  • LINQのOrderBy / OrderByDescending:非破壊的に並び替え、新しいコレクションを返す。

1-4. SortとOrderByの使い分け早見表

メソッド破壊的か戻り値利点
List.Sort()はいvoidシンプルで高速
Array.Sort()はいvoid配列専用、高速
OrderBy / OrderByDescendingいいえIEnumerable<T>元データ保持、LINQチェーン可能

2. ListをSortで昇順に並び替える基本

2-1. List.Sort()の基本構文

C#
List<int> numbers = new List<int> {3, 1, 4, 2};
numbers.Sort();

これだけでリストが昇順に並び替えられます。

2-2. 数値のListを昇順にソートする

整数や小数のリストは、Sort()を呼ぶだけで自然な数値順に並びます。

2-3. 文字列のListを昇順にソートする

文字列もSort()でアルファベット順に並び替え可能です。日本語の場合はカルチャに注意する必要があります。

2-4. DateTimeのListを日付順にソートする

C#
List<DateTime> dates = new List<DateTime> { DateTime.Now, DateTime.Now.AddDays(-1) };
dates.Sort();

日付が古い順に並びます。

2-5. List.Sort()は元のList自体を並び替える点に注意

Sort()はリストを直接書き換えるため、元の順序を保持したい場合はコピーを作る必要があります。

3. Listを降順に並び替える方法

3-1. Sort後にReverse()で降順にする

C#
numbers.Sort();
numbers.Reverse();

簡単ですが、二度処理が発生します。

3-2. Comparisonを使って降順ソートする

C#
numbers.Sort((a, b) => b.CompareTo(a));

直接降順にソートできます。

3-3. LINQのOrderByDescendingで降順にする

C#
var descendingNumbers = numbers.OrderByDescending(n => n).ToList();

元のリストを保持しつつ新しいリストを作成可能です。

3-4. 降順ソートでよくあるミスと対処法

  • 元データを直接変更してしまう

  • nullや空文字の扱いで例外が発生

  • 文字列の大文字・小文字で思った順にならない

対策として、nullチェックやカルチャ設定を利用します。

4. 配列をArray.Sortで並び替える方法

4-1. Array.Sort()の基本構文

C#
int[] array = {3, 1, 4, 2};
Array.Sort(array);

配列の要素が昇順に並びます。

4-2. int配列を昇順にソートする

整数配列はArray.Sort()で簡単に昇順に並べ替えられます。

4-3. string配列を昇順にソートする

文字列配列もArray.Sort()でアルファベット順に並べ替え可能。日本語はStringComparerを指定すると自然な順序に。

4-4. 配列を降順にソートする

C#
Array.Sort(array);
Array.Reverse(array);

またはArray.Sort(array, (a,b) => b.CompareTo(a));で直接降順も可能。

4-5. Array.SortとList.Sortの違い

  • 配列専用かリスト専用か

  • 両方とも破壊的

  • LINQとの相性や拡張性の違い

5. オブジェクトのListをプロパティでソートする

5-1. クラスや構造体のListをソートする考え方

オブジェクトの特定プロパティで並び替える場合、Comparison<T>OrderByでプロパティを指定します。

5-2. 年齢・価格・スコアなど数値プロパティで並び替える

C#
users.Sort((a,b) => a.Age.CompareTo(b.Age));

5-3. 名前など文字列プロパティで並び替える

C#
users.Sort((a,b) => string.Compare(a.Name, b.Name));

5-4. 日付プロパティで新しい順・古い順に並び替える

C#
users.Sort((a,b) => b.JoinDate.CompareTo(a.JoinDate));

5-5. nullを含むプロパティを安全にソートする方法

C#
users.Sort((a,b) => (a.Name ?? "").CompareTo(b.Name ?? ""));

nullを空文字に置き換えることで例外を回避。

6. 独自条件で並び替えるカスタムソート

6-1. Comparison<T>を使ったカスタムソート

C#
list.Sort((x, y) => x.Score - y.Score);

複雑な条件でも一つのラムダで定義可能。

6-2. ラムダ式で簡潔に比較条件を書く

数値や文字列の複数条件も短く記述可能です。

6-3. IComparer<T>を使って比較ロジックを分離する

独自のクラスで比較をまとめ、再利用性を高められます。

6-4. IComparable<T>を実装してデフォルトの並び順を定義する

クラス自体に並び順を定義することで、Sort()だけで自然順序に並べ替え可能です。

6-5. 特定の順番を指定して並び替える方法

優先度リストやカスタム順序を事前に定義し、比較関数で参照する方法があります。

7. LINQでソートするOrderBy・ThenByの使い方

7-1. OrderByで昇順に並び替える

C#
var sorted = users.OrderBy(u => u.Age).ToList();

7-2. OrderByDescendingで降順に並び替える

C#
var sortedDesc = users.OrderByDescending(u => u.Age).ToList();

7-3. ThenByで複数条件のソートを行う

C#
var sorted = users.OrderBy(u => u.Age).ThenBy(u => u.Name).ToList();

7-4. ThenByDescendingを組み合わせる

数値は昇順、名前は降順など柔軟に指定可能です。

7-5. ToList()やToArray()が必要になるケース

LINQはIEnumerable<T>を返すため、リストや配列に変換する場合はToList()ToArray()を使用します。

8. SortとOrderByの違いを理解する

8-1. Sortは破壊的ソート、OrderByは非破壊的ソート

元のデータを変更するか、新しいコレクションを作るかの違いです。

8-2. 戻り値の違い

  • Sort():void

  • OrderBy():IEnumerable<T>

8-3. パフォーマンス面の違い

小規模データは差が少ないですが、大規模データではSort()の方が高速な場合があります。

8-4. 実務ではどちらを使うべきか

元データを保持したい場合はOrderBy、直接書き換えて高速化したい場合はSortがおすすめです。

8-5. 元データを保持したい場合の書き方

C#
var newList = oldList.OrderBy(x => x.Value).ToList();

9. 実務でよく使うC#ソートの実例

9-1. ユーザー一覧を名前順に並び替える

C#
users.Sort((a,b) => string.Compare(a.Name, b.Name));

9-2. 商品一覧を価格の安い順・高い順に並び替える

C#
products.Sort((a,b) => a.Price.CompareTo(b.Price)); // 安い順
products.Sort((a,b) => b.Price.CompareTo(a.Price)); // 高い順

9-3. ランキングをスコア順に並び替える

スコアが高い順にSort((a,b) => b.Score.CompareTo(a.Score))で並べます。

9-4. 更新日時の新しい順に並び替える

DateTimeプロパティを使って降順ソート。

9-5. 複数条件で一覧表示を並び替える

LINQのOrderBy().ThenBy()で複数条件を組み合わせ、実務でよく使われます。

10. C#のSortでつまずきやすい注意点

10-1. Sort()の戻り値を代入しようとしてエラーになる

Sort()はvoidなので、代入は不要です。

10-2. 文字列ソートで大文字・小文字や日本語の順序が想定と違う

StringComparer.OrdinalIgnoreCaseやカルチャを指定することで対応可能。

10-3. nullを含むデータで例外や不自然な並び順になる

??演算子でnullを置き換えることで安全にソート可能です。

10-4. 独自クラスで比較方法を指定せずにSortして失敗する

IComparableComparisonを実装しておくことが重要です。

10-5. 安定ソートが必要な場合の考え方

Sort()は安定ソートではないため、順序保持が必要な場合はOrderByを使うのがおすすめです。

11. C# Sortのよくある質問

11-1. List.Sort()で降順にする一番簡単な方法は?

C#
numbers.Sort();
numbers.Reverse();

11-2. 配列を降順にソートするには?

C#
Array.Sort(array);
Array.Reverse(array);

または比較関数で直接降順に指定可能。

11-3. オブジェクトを複数条件でソートするには?

LINQのOrderBy().ThenBy()またはSort()Comparisonを組み合わせます。

11-4. SortとOrderByはどちらが速い?

小規模は差が少ないですが、大規模データではSort()が高速な場合があります。

11-5. 元のListを変更せずに並び替えるには?

C#
var newList = oldList.OrderBy(x => x.Value).ToList();

まとめ

C#のソートは、List.Sort()Array.Sort()での破壊的ソートと、LINQのOrderBy/OrderByDescendingでの非破壊的ソートに大別されます。昇順・降順の基本から、オブジェクトのプロパティや独自条件でのカスタムソートまで幅広く対応可能です。実務では、元データを保持したい場合や複数条件で並び替えたい場合など、状況に応じて適切な方法を選ぶことが重要です。