C#のソート方法を完全解説|List・配列・LINQの並び替えを初心者向けにわかりやすく紹介
はじめに
C#でプログラムを書いていると、数値や文字列、ユーザー情報、商品一覧、日付データなどを「並び替えたい」と感じる場面がよくあります。たとえば、点数の高い順にランキングを表示したり、名前をあいうえお順に並べたり、作成日が新しい順にデータを表示したりする処理です。
このような並び替え処理を「ソート」と呼びます。C#には、Listを並び替えるSort()、配列を並び替えるArray.Sort()、元データを変更せずに並び替えられるLINQのOrderBy()など、複数のソート方法があります。
この記事では、「c# ソート」で調べている初心者の方に向けて、C#のソート方法を基礎からわかりやすく解説します。List、配列、LINQ、オブジェクトのリスト、複数条件のソート、独自ルールのソートまで、サンプルコード付きで紹介します。
1. C#のソートとは?並び替えの基本を初心者向けに解説
C#のソートを理解するには、まず「ソートとは何か」「昇順と降順の違い」「どの方法を使えばよいのか」を押さえておくことが大切です。
C#では、扱うデータの種類によって適したソート方法が変わります。Listを直接並び替える場合、配列を並び替える場合、元データを残したまま新しい並び順を作りたい場合で、使うメソッドが異なります。
1-1. ソートとはデータを一定の順番に並び替える処理
ソートとは、データを決められたルールに従って並び替える処理のことです。
たとえば、次のような数値のリストがあるとします。
C#List<int> numbers = new List<int> { 5, 2, 8, 1, 3 };
このデータを小さい順に並び替えると、次のようになります。
C#1, 2, 3, 5, 8
このように、バラバラに並んでいるデータを一定の順番に整える処理がソートです。
ソートは、一覧表示、検索結果、ランキング、日付順の表示、名前順の表示など、さまざまな場面で使われます。
1-2. 昇順と降順の違い
ソートには、大きく分けて「昇順」と「降順」があります。
昇順は、小さいものから大きいものへ並べる順番です。
C#1, 2, 3, 4, 5
文字列の場合は、アルファベット順や辞書順のような並びになります。
C#apple, banana, orange
降順は、大きいものから小さいものへ並べる順番です。
C#5, 4, 3, 2, 1
文字列の場合は、昇順とは逆の順番になります。
C#orange, banana, apple
C#でソートを行うときは、「昇順にしたいのか」「降順にしたいのか」を最初に決めると、使うメソッドを選びやすくなります。
1-3. C#でよく使うソート方法の種類
C#でよく使うソート方法には、主に次のようなものがあります。
C#List<T>.Sort()
Array.Sort()
LINQのOrderBy()
LINQのOrderByDescending()
LINQのThenBy()
LINQのThenByDescending()
List<T>.Sort()は、Listを直接並び替えるためのメソッドです。元のリスト自体が変更されます。
Array.Sort()は、配列を直接並び替えるためのメソッドです。こちらも元の配列自体が変更されます。
LINQのOrderBy()やOrderByDescending()は、元のデータを変更せずに、並び替えた結果を新しく取得する方法です。複数条件でソートしたいときにもよく使われます。
1-4. List・配列・LINQの使い分け早見表
C#のソート方法は、目的に応じて使い分けるとわかりやすくなります。
| やりたいこと | 使う方法 | 元データの変更 |
|---|---|---|
| Listを直接並び替えたい | List.Sort() | 変更される |
| 配列を直接並び替えたい | Array.Sort() | 変更される |
| 元データを残したい | OrderBy() | 変更されない |
| 降順に並び替えたい | OrderByDescending()またはReverse() | 方法による |
| 複数条件で並び替えたい | OrderBy() + ThenBy() | 変更されない |
| 独自ルールで並び替えたい | ComparisonやIComparer | 方法による |
初心者のうちは、まず次のように覚えるとよいでしょう。
Listをそのまま並び替えたいならSort()、配列ならArray.Sort()、元データを残したいならLINQのOrderBy()を使います。
2. C#でListをソートする方法
C#でListをソートする場合は、List<T>クラスのSort()メソッドを使うのが基本です。
List.Sort()は、リストの中身を直接並び替えます。数値や文字列のように比較方法が決まっているデータであれば、簡単に昇順ソートできます。
2-1. List.Sort()で昇順に並び替える
List.Sort()を使うと、リストを昇順に並び替えられます。
C#using System;
using System.Collections.Generic;
class Program
{
static void Main()
{
List<int> numbers = new List<int> { 5, 2, 8, 1, 3 };
numbers.Sort();
foreach (int number in numbers)
{
Console.WriteLine(number);
}
}
}
実行結果は次のようになります。
C#1
2
3
5
8
numbers.Sort();を実行するだけで、List<int>の中身が小さい順に並び替えられます。
2-2. List.Sort()とReverse()で降順に並び替える
List.Sort()は基本的に昇順で並び替えます。降順にしたい場合は、Sort()で昇順に並び替えたあと、Reverse()で順番を逆にする方法があります。
C#using System;
using System.Collections.Generic;
class Program
{
static void Main()
{
List<int> numbers = new List<int> { 5, 2, 8, 1, 3 };
numbers.Sort();
numbers.Reverse();
foreach (int number in numbers)
{
Console.WriteLine(number);
}
}
}
実行結果は次のようになります。
C#8
5
3
2
1
この方法はシンプルなので、初心者にもわかりやすい降順ソートです。
ただし、条件が複雑な場合はComparisonを使ったソートや、LINQのOrderByDescending()を使うほうが読みやすくなります。
2-3. Comparisonを使って降順や条件付きソートを行う
List.Sort()には、比較方法を指定することもできます。ラムダ式を使うと、降順や条件付きソートを簡単に書けます。
C#using System;
using System.Collections.Generic;
class Program
{
static void Main()
{
List<int> numbers = new List<int> { 5, 2, 8, 1, 3 };
numbers.Sort((a, b) => b.CompareTo(a));
foreach (int number in numbers)
{
Console.WriteLine(number);
}
}
}
実行結果は次のようになります。
C#8
5
3
2
1
a.CompareTo(b)にすると昇順、b.CompareTo(a)にすると降順になります。
C#numbers.Sort((a, b) => a.CompareTo(b)); // 昇順
numbers.Sort((a, b) => b.CompareTo(a)); // 降順
Comparisonを使うと、単純な昇順・降順だけでなく、独自の条件で並び替えることもできます。
2-4. 数値のListをソートするサンプルコード
数値のListをソートする基本例を見てみましょう。
C#using System;
using System.Collections.Generic;
class Program
{
static void Main()
{
List<int> scores = new List<int> { 80, 95, 70, 60, 100 };
scores.Sort();
Console.WriteLine("昇順:");
foreach (int score in scores)
{
Console.WriteLine(score);
}
scores.Reverse();
Console.WriteLine("降順:");
foreach (int score in scores)
{
Console.WriteLine(score);
}
}
}
実行結果は次のようになります。
C#昇順:
60
70
80
95
100
降順:
100
95
80
70
60
点数や価格、年齢、数量などの数値データは、このように簡単にソートできます。
2-5. 文字列のListをソートするサンプルコード
文字列のListも、Sort()で並び替えられます。
C#using System;
using System.Collections.Generic;
class Program
{
static void Main()
{
List<string> fruits = new List<string>
{
"orange",
"apple",
"banana",
"grape"
};
fruits.Sort();
foreach (string fruit in fruits)
{
Console.WriteLine(fruit);
}
}
}
実行結果は次のようになります。
C#apple
banana
grape
orange
文字列の場合は、アルファベット順のような形で並び替えられます。
日本語の文字列を扱う場合は、環境や比較方法によって期待する順番と異なることがあります。五十音順などを厳密に扱いたい場合は、文化情報や比較ルールを意識する必要があります。
2-6. List.Sort()は元のListを直接変更する点に注意
List.Sort()を使うと、元のList自体が変更されます。
C#List<int> numbers = new List<int> { 5, 2, 8, 1, 3 };
numbers.Sort();
// numbersの中身はすでに並び替わっている
つまり、ソート前の順番をあとで使いたい場合は注意が必要です。
元の順番を残したい場合は、コピーを作ってからソートする方法があります。
C#List<int> numbers = new List<int> { 5, 2, 8, 1, 3 };
List<int> sortedNumbers = new List<int>(numbers);
sortedNumbers.Sort();
または、LINQのOrderBy()を使う方法もあります。
C#List<int> sortedNumbers = numbers.OrderBy(x => x).ToList();
元データを変更したくない場合は、List.Sort()ではなくLINQを使うと安全です。
3. C#で配列をソートする方法
C#で配列をソートする場合は、Array.Sort()を使います。
Array.Sort()は、配列の中身を直接並び替えるメソッドです。int[]やstring[]など、配列を扱っている場合に便利です。
3-1. Array.Sort()で配列を昇順に並び替える
配列を昇順に並び替える基本コードは次のとおりです。
C#using System;
class Program
{
static void Main()
{
int[] numbers = { 5, 2, 8, 1, 3 };
Array.Sort(numbers);
foreach (int number in numbers)
{
Console.WriteLine(number);
}
}
}
実行結果は次のようになります。
C#1
2
3
5
8
Array.Sort(numbers);を実行すると、配列の中身が昇順に並び替えられます。
3-2. Array.Reverse()を組み合わせて降順に並び替える
配列を降順にしたい場合は、Array.Sort()で昇順に並び替えたあと、Array.Reverse()で逆順にします。
C#using System;
class Program
{
static void Main()
{
int[] numbers = { 5, 2, 8, 1, 3 };
Array.Sort(numbers);
Array.Reverse(numbers);
foreach (int number in numbers)
{
Console.WriteLine(number);
}
}
}
実行結果は次のようになります。
C#8
5
3
2
1
この方法は、配列を降順に並び替える基本的な書き方です。
3-3. 文字列配列をソートする方法
文字列の配列もArray.Sort()でソートできます。
C#using System;
class Program
{
static void Main()
{
string[] names = { "Taro", "Hanako", "Jiro", "Aiko" };
Array.Sort(names);
foreach (string name in names)
{
Console.WriteLine(name);
}
}
}
実行結果は次のようになります。
C#Aiko
Hanako
Jiro
Taro
文字列配列を並び替えると、通常は文字列の比較ルールに従って昇順に並びます。
3-4. 数値配列をソートする方法
数値配列のソートは、ランキングや集計処理でよく使われます。
C#using System;
class Program
{
static void Main()
{
int[] prices = { 1200, 500, 3000, 800, 1500 };
Array.Sort(prices);
Console.WriteLine("価格の安い順:");
foreach (int price in prices)
{
Console.WriteLine(price);
}
}
}
実行結果は次のようになります。
C#価格の安い順:
500
800
1200
1500
3000
価格の安い順、年齢の若い順、点数の低い順など、数値を昇順に並べたいときに使えます。
3-5. 配列の一部だけをソートする方法
Array.Sort()では、配列全体だけでなく一部だけをソートすることもできます。
C#using System;
class Program
{
static void Main()
{
int[] numbers = { 9, 5, 2, 8, 1, 7 };
Array.Sort(numbers, 1, 4);
foreach (int number in numbers)
{
Console.WriteLine(number);
}
}
}
実行結果は次のようになります。
C#9
1
2
5
8
7
このコードでは、インデックス1から4個の要素をソートしています。
対象になる部分は次の範囲です。
C#5, 2, 8, 1
これが昇順に並び替えられて、次のようになります。
C#1, 2, 5, 8
配列の一部だけを並び替えたい場合に便利です。
3-6. Array.Sort()も元の配列を直接変更する点に注意
Array.Sort()もList.Sort()と同じように、元の配列を直接変更します。
C#int[] numbers = { 5, 2, 8, 1, 3 };
Array.Sort(numbers);
// numbersの中身は並び替わっている
ソート前の配列を残したい場合は、コピーを作ってからソートしましょう。
C#int[] numbers = { 5, 2, 8, 1, 3 };
int[] sortedNumbers = (int[])numbers.Clone();
Array.Sort(sortedNumbers);
またはLINQを使って、新しい配列として取得することもできます。
C#int[] sortedNumbers = numbers.OrderBy(x => x).ToArray();
元データを残したい場合は、Array.Sort()を直接使う前にコピーを作ることが重要です。
4. LINQを使ってC#でソートする方法
C#では、LINQを使ってデータをソートすることもできます。
LINQのソートは、OrderBy()やOrderByDescending()を使います。List.Sort()やArray.Sort()と違い、元のデータを直接変更しない点が大きな特徴です。
LINQを使う場合は、次の名前空間を追加します。
C#using System.Linq;
4-1. OrderBy()で昇順に並び替える
OrderBy()を使うと、データを昇順に並び替えられます。
C#using System;
using System.Collections.Generic;
using System.Linq;
class Program
{
static void Main()
{
List<int> numbers = new List<int> { 5, 2, 8, 1, 3 };
var sortedNumbers = numbers.OrderBy(x => x);
foreach (int number in sortedNumbers)
{
Console.WriteLine(number);
}
}
}
実行結果は次のようになります。
C#1
2
3
5
8
x => xは、「要素そのものを基準に並び替える」という意味です。
数値のリストであれば、数値そのものを基準に昇順で並び替えられます。
4-2. OrderByDescending()で降順に並び替える
降順に並び替えたい場合は、OrderByDescending()を使います。
C#using System;
using System.Collections.Generic;
using System.Linq;
class Program
{
static void Main()
{
List<int> numbers = new List<int> { 5, 2, 8, 1, 3 };
var sortedNumbers = numbers.OrderByDescending(x => x);
foreach (int number in sortedNumbers)
{
Console.WriteLine(number);
}
}
}
実行結果は次のようになります。
C#8
5
3
2
1
LINQを使うと、Sort()してからReverse()する必要がなく、降順ソートをわかりやすく書けます。
4-3. ToList()やToArray()で結果をList・配列に変換する
OrderBy()の結果は、そのままではListや配列ではありません。必要に応じて、ToList()やToArray()で変換します。
Listとして取得する場合は次のように書きます。
C#List<int> sortedList = numbers.OrderBy(x => x).ToList();
配列として取得する場合は次のように書きます。
C#int[] sortedArray = numbers.OrderBy(x => x).ToArray();
実際のコード例は次のとおりです。
C#using System;
using System.Collections.Generic;
using System.Linq;
class Program
{
static void Main()
{
List<int> numbers = new List<int> { 5, 2, 8, 1, 3 };
List<int> sortedList = numbers.OrderBy(x => x).ToList();
foreach (int number in sortedList)
{
Console.WriteLine(number);
}
}
}
LINQの結果をあとで何度も使いたい場合は、ToList()やToArray()で確定させておくと扱いやすくなります。
4-4. LINQのソートは元データを変更しない
LINQのOrderBy()は、元のデータを変更しません。
C#using System;
using System.Collections.Generic;
using System.Linq;
class Program
{
static void Main()
{
List<int> numbers = new List<int> { 5, 2, 8, 1, 3 };
List<int> sortedNumbers = numbers.OrderBy(x => x).ToList();
Console.WriteLine("元のList:");
foreach (int number in numbers)
{
Console.WriteLine(number);
}
Console.WriteLine("ソート後のList:");
foreach (int number in sortedNumbers)
{
Console.WriteLine(number);
}
}
}
実行結果は次のようになります。
C#元のList:
5
2
8
1
3
ソート後のList:
1
2
3
5
8
このように、元のnumbersは変更されず、並び替えた結果がsortedNumbersに入ります。
4-5. List.Sort()とLINQ OrderBy()の違い
List.Sort()とLINQのOrderBy()は、どちらもソートに使えますが、動きが異なります。
List.Sort()は、元のリストを直接変更します。
C#numbers.Sort();
一方、OrderBy()は元のリストを変更せず、並び替えた結果を返します。
C#List<int> sortedNumbers = numbers.OrderBy(x => x).ToList();
違いをまとめると、次のようになります。
| 比較項目 | List.Sort() | OrderBy() |
|---|---|---|
| 元データ | 変更される | 変更されない |
| 戻り値 | なし | 並び替え結果 |
| 複数条件 | やや書きにくい | 書きやすい |
| 初心者へのわかりやすさ | 単純なソート向き | 柔軟で読みやすい |
| 主な用途 | Listを直接並び替える | 新しい並び順を作る |
元のデータを変更してよいならList.Sort()、元のデータを残したいならOrderBy()を使うとよいでしょう。
5. オブジェクトやクラスのリストをソートする方法
実際の開発では、数値や文字列だけでなく、クラスのオブジェクトをソートすることがよくあります。
たとえば、ユーザー一覧を年齢順に並べたり、商品一覧を価格順に並べたり、成績一覧を点数順に並べたりするケースです。
オブジェクトのリストをソートする場合は、「どのプロパティを基準に並び替えるか」を指定します。
5-1. プロパティを指定してソートする基本
まず、次のようなPersonクラスがあるとします。
C#class Person
{
public string Name { get; set; }
public int Age { get; set; }
}
このPersonのリストを、年齢順に並び替える例です。
C#using System;
using System.Collections.Generic;
using System.Linq;
class Person
{
public string Name { get; set; }
public int Age { get; set; }
}
class Program
{
static void Main()
{
List<Person> people = new List<Person>
{
new Person { Name = "Taro", Age = 30 },
new Person { Name = "Hanako", Age = 25 },
new Person { Name = "Jiro", Age = 20 }
};
List<Person> sortedPeople = people.OrderBy(p => p.Age).ToList();
foreach (Person person in sortedPeople)
{
Console.WriteLine($"{person.Name}: {person.Age}");
}
}
}
実行結果は次のようになります。
C#Jiro: 20
Hanako: 25
Taro: 30
p => p.Ageと書くことで、「Ageプロパティを基準に並び替える」という意味になります。
5-2. 年齢や点数など数値プロパティで並び替える
年齢、点数、価格、在庫数などの数値プロパティは、OrderBy()やOrderByDescending()で簡単にソートできます。
次は、点数の高い順に並び替える例です。
C#using System;
using System.Collections.Generic;
using System.Linq;
class Student
{
public string Name { get; set; }
public int Score { get; set; }
}
class Program
{
static void Main()
{
List<Student> students = new List<Student>
{
new Student { Name = "Taro", Score = 80 },
new Student { Name = "Hanako", Score = 95 },
new Student { Name = "Jiro", Score = 70 }
};
List<Student> sortedStudents = students
.OrderByDescending(s => s.Score)
.ToList();
foreach (Student student in sortedStudents)
{
Console.WriteLine($"{student.Name}: {student.Score}");
}
}
}
実行結果は次のようになります。
C#Hanako: 95
Taro: 80
Jiro: 70
ランキング表示のように、高い値から順番に表示したい場合はOrderByDescending()が便利です。
5-3. 名前など文字列プロパティで並び替える
名前やカテゴリ名などの文字列プロパティでもソートできます。
C#using System;
using System.Collections.Generic;
using System.Linq;
class Person
{
public string Name { get; set; }
public int Age { get; set; }
}
class Program
{
static void Main()
{
List<Person> people = new List<Person>
{
new Person { Name = "Taro", Age = 30 },
new Person { Name = "Hanako", Age = 25 },
new Person { Name = "Jiro", Age = 20 },
new Person { Name = "Aiko", Age = 28 }
};
List<Person> sortedPeople = people.OrderBy(p => p.Name).ToList();
foreach (Person person in sortedPeople)
{
Console.WriteLine($"{person.Name}: {person.Age}");
}
}
}
実行結果は次のようになります。
C#Aiko: 28
Hanako: 25
Jiro: 20
Taro: 30
文字列プロパティを基準にすると、名前順やカテゴリ順の一覧を作れます。
5-4. 複数条件でソートするThenBy()の使い方
複数条件でソートしたい場合は、OrderBy()のあとにThenBy()を使います。
たとえば、まず年齢順に並び替え、同じ年齢の場合は名前順に並び替える例です。
C#using System;
using System.Collections.Generic;
using System.Linq;
class Person
{
public string Name { get; set; }
public int Age { get; set; }
}
class Program
{
static void Main()
{
List<Person> people = new List<Person>
{
new Person { Name = "Taro", Age = 30 },
new Person { Name = "Hanako", Age = 25 },
new Person { Name = "Aiko", Age = 25 },
new Person { Name = "Jiro", Age = 20 }
};
List<Person> sortedPeople = people
.OrderBy(p => p.Age)
.ThenBy(p => p.Name)
.ToList();
foreach (Person person in sortedPeople)
{
Console.WriteLine($"{person.Name}: {person.Age}");
}
}
}
実行結果は次のようになります。
C#Jiro: 20
Aiko: 25
Hanako: 25
Taro: 30
最初にAgeで昇順ソートし、Ageが同じ場合はNameで昇順ソートしています。
5-5. 降順と昇順を組み合わせて並び替える方法
複数条件では、昇順と降順を組み合わせることもできます。
たとえば、点数は高い順、同じ点数の場合は名前順に並び替える例です。
C#using System;
using System.Collections.Generic;
using System.Linq;
class Student
{
public string Name { get; set; }
public int Score { get; set; }
}
class Program
{
static void Main()
{
List<Student> students = new List<Student>
{
new Student { Name = "Taro", Score = 80 },
new Student { Name = "Hanako", Score = 95 },
new Student { Name = "Aiko", Score = 95 },
new Student { Name = "Jiro", Score = 70 }
};
List<Student> sortedStudents = students
.OrderByDescending(s => s.Score)
.ThenBy(s => s.Name)
.ToList();
foreach (Student student in sortedStudents)
{
Console.WriteLine($"{student.Name}: {student.Score}");
}
}
}
実行結果は次のようになります。
C#Aiko: 95
Hanako: 95
Taro: 80
Jiro: 70
OrderByDescending()で点数を降順にし、ThenBy()で名前を昇順にしています。
降順の条件を追加したい場合は、ThenByDescending()を使います。
C#.OrderByDescending(s => s.Score)
.ThenByDescending(s => s.Name)
このように、LINQを使うと複数条件のソートを読みやすく書けます。
6. C#で条件を指定してソートする応用テクニック
基本的な昇順・降順だけでなく、C#では条件を指定して柔軟にソートできます。
「特定の値を先頭にしたい」「nullを後ろにしたい」「大文字・小文字を区別せずに並び替えたい」「日付順に並べたい」など、実務では少し複雑なソートが必要になることもあります。
6-1. ラムダ式を使ったカスタムソート
List.Sort()では、ラムダ式を使って比較ルールを指定できます。
次の例では、文字列の長さが短い順にソートします。
C#using System;
using System.Collections.Generic;
class Program
{
static void Main()
{
List<string> words = new List<string>
{
"banana",
"apple",
"kiwi",
"orange"
};
words.Sort((a, b) => a.Length.CompareTo(b.Length));
foreach (string word in words)
{
Console.WriteLine(word);
}
}
}
実行結果は次のようになります。
C#kiwi
apple
banana
orange
a.Length.CompareTo(b.Length)と書くことで、文字数を基準に昇順で並び替えています。
降順にしたい場合は、比較する順番を逆にします。
C#words.Sort((a, b) => b.Length.CompareTo(a.Length));
ラムダ式を使うと、短いコードで独自のソート条件を書けます。
6-2. IComparerを使って独自ルールでソートする
より複雑なルールを使いたい場合は、IComparer<T>を実装したクラスを作る方法があります。
次の例では、文字列の長さでソートするIComparerを作っています。
C#using System;
using System.Collections.Generic;
class LengthComparer : IComparer<string>
{
public int Compare(string x, string y)
{
return x.Length.CompareTo(y.Length);
}
}
class Program
{
static void Main()
{
List<string> words = new List<string>
{
"banana",
"apple",
"kiwi",
"orange"
};
words.Sort(new LengthComparer());
foreach (string word in words)
{
Console.WriteLine(word);
}
}
}
実行結果は次のようになります。
C#kiwi
apple
banana
orange
IComparerを使うと、比較ルールをクラスとして分けられるため、同じソート条件を複数箇所で使い回しやすくなります。
6-3. nullを含むデータを安全にソートする
文字列やオブジェクトのリストには、nullが含まれることがあります。nullを考慮せずにソートすると、意図しない結果やエラーの原因になる場合があります。
LINQを使うと、nullを最後に並べるような処理を書けます。
C#using System;
using System.Collections.Generic;
using System.Linq;
class Program
{
static void Main()
{
List<string> names = new List<string>
{
"Taro",
null,
"Hanako",
"Jiro"
};
List<string> sortedNames = names
.OrderBy(name => name == null)
.ThenBy(name => name)
.ToList();
foreach (string name in sortedNames)
{
Console.WriteLine(name ?? "null");
}
}
}
実行結果は次のようになります。
C#Hanako
Jiro
Taro
null
OrderBy(name => name == null)により、nullではないものが先に並び、nullが後ろになります。
nullを先頭にしたい場合は、条件を調整します。
C#List<string> sortedNames = names
.OrderByDescending(name => name == null)
.ThenBy(name => name)
.ToList();
オブジェクトのプロパティがnullになる可能性がある場合も、同じように注意してソートしましょう。
6-4. 大文字・小文字を区別せずに文字列をソートする
文字列をソートするとき、大文字・小文字を区別したくない場合があります。
その場合は、StringComparerを使うと便利です。
C#using System;
using System.Collections.Generic;
class Program
{
static void Main()
{
List<string> words = new List<string>
{
"banana",
"Apple",
"orange",
"Grape"
};
words.Sort(StringComparer.OrdinalIgnoreCase);
foreach (string word in words)
{
Console.WriteLine(word);
}
}
}
実行結果は次のようになります。
C#Apple
banana
Grape
orange
StringComparer.OrdinalIgnoreCaseを指定することで、大文字・小文字を区別せずに比較できます。
LINQで書く場合は、次のようにします。
C#List<string> sortedWords = words
.OrderBy(word => word, StringComparer.OrdinalIgnoreCase)
.ToList();
文字列のソートでは、大文字・小文字、文化圏、全角・半角などの違いが結果に影響することがあります。必要に応じて比較方法を明示すると、意図した並び順にしやすくなります。
6-5. 日付やDateTimeをソートする方法
日付をソートする場合は、DateTimeを使います。
次の例では、日付を古い順に並び替えます。
C#using System;
using System.Collections.Generic;
using System.Linq;
class Program
{
static void Main()
{
List<DateTime> dates = new List<DateTime>
{
new DateTime(2024, 5, 1),
new DateTime(2024, 1, 10),
new DateTime(2024, 3, 15)
};
List<DateTime> sortedDates = dates.OrderBy(date => date).ToList();
foreach (DateTime date in sortedDates)
{
Console.WriteLine(date.ToString("yyyy/MM/dd"));
}
}
}
実行結果は次のようになります。
C#2024/01/10
2024/03/15
2024/05/01
新しい順にしたい場合は、OrderByDescending()を使います。
C#List<DateTime> sortedDates = dates
.OrderByDescending(date => date)
.ToList();
オブジェクトの中に日付プロパティがある場合も、同じように書けます。
C#List<Article> sortedArticles = articles
.OrderByDescending(article => article.CreatedAt)
.ToList();
新着記事一覧や更新日時順の表示などでよく使うソート方法です。
7. C#のソートでよくあるエラー・注意点
C#のソートで初心者がつまずきやすいポイントは、Sort()とOrderBy()の違いです。
特に、「OrderBy()を書いたのに並び替わらない」「Sort()の結果を変数に入れようとしてエラーになる」といったケースはよくあります。
7-1. Sort()とOrderBy()の戻り値の違い
List.Sort()は、元のリストを直接変更するメソッドです。そのため、戻り値はありません。
次のような書き方はできません。
C#List<int> sortedNumbers = numbers.Sort(); // エラー
Sort()は戻り値を返さないため、変数に代入できません。
正しくは次のように書きます。
C#numbers.Sort();
一方、LINQのOrderBy()は、並び替えた結果を返します。
C#List<int> sortedNumbers = numbers.OrderBy(x => x).ToList();
この違いを理解しておくと、ソート処理で混乱しにくくなります。
7-2. OrderBy()したのに並び替わらない原因
OrderBy()を使ったのに、元のリストが並び替わっていないと感じることがあります。
たとえば、次のコードを見てください。
C#List<int> numbers = new List<int> { 5, 2, 8, 1, 3 };
numbers.OrderBy(x => x);
foreach (int number in numbers)
{
Console.WriteLine(number);
}
この場合、元のnumbersは変更されません。
OrderBy()は、並び替えた結果を返すだけで、元のリストを直接変更しないからです。
正しくは、結果を変数に代入します。
C#List<int> sortedNumbers = numbers.OrderBy(x => x).ToList();
または、元の変数に代入し直します。
C#numbers = numbers.OrderBy(x => x).ToList();
OrderBy()を使うときは、「結果を受け取る」ことを忘れないようにしましょう。
7-3. ToList()を忘れて結果が反映されないケース
LINQのOrderBy()は、IOrderedEnumerable<T>という形で結果を返します。
そのままforeachで使うことはできますが、Listとして扱いたい場合はToList()が必要です。
C#var sortedNumbers = numbers.OrderBy(x => x);
この書き方でも並び替え結果を列挙できますが、List<int>として変数に入れたい場合は次のようにします。
C#List<int> sortedNumbers = numbers.OrderBy(x => x).ToList();
配列にしたい場合はToArray()を使います。
C#int[] sortedNumbers = numbers.OrderBy(x => x).ToArray();
LINQでソートした結果を保存したい場合は、ToList()やToArray()を使うと覚えておきましょう。
7-4. 元データを変更したくないときの対処法
元データを変更したくない場合は、Sort()やArray.Sort()を直接使うのではなく、コピーを作るかLINQを使います。
Listをコピーしてからソートする例です。
C#List<int> numbers = new List<int> { 5, 2, 8, 1, 3 };
List<int> sortedNumbers = new List<int>(numbers);
sortedNumbers.Sort();
LINQを使う例です。
C#List<int> sortedNumbers = numbers.OrderBy(x => x).ToList();
配列の場合は、Clone()を使ってコピーできます。
C#int[] numbers = { 5, 2, 8, 1, 3 };
int[] sortedNumbers = (int[])numbers.Clone();
Array.Sort(sortedNumbers);
元の順番が必要になる可能性がある場合は、直接ソートする前にコピーを作るようにしましょう。
7-5. 比較できない型をソートするときの注意点
Sort()やOrderBy()では、データ同士を比較する必要があります。
数値や文字列、日付のように比較方法が明確な型は、そのままソートできます。しかし、自作クラスの場合は、どのプロパティで比較するのかを指定する必要があります。
たとえば、次のようなコードは意図どおりに動かない場合があります。
C#List<Person> people = new List<Person>();
people.Sort();
Person同士をどのように比較するのかがわからないためです。
この場合は、LINQでプロパティを指定するのが簡単です。
C#List<Person> sortedPeople = people.OrderBy(p => p.Age).ToList();
または、Sort()で比較条件を指定します。
C#people.Sort((a, b) => a.Age.CompareTo(b.Age));
自作クラスをソートするときは、「何を基準に並び替えるのか」を明確に指定しましょう。
8. C#のソート方法はどれを使うべき?
C#には複数のソート方法があるため、初心者のうちは「結局どれを使えばいいのか」と迷いやすいです。
選び方のポイントは、次の3つです。
元データを変更してよいか、データ型がListか配列か、ソート条件が単純か複雑かです。
8-1. Listを直接並び替えたいならList.Sort()
Listを直接並び替えたい場合は、List.Sort()を使います。
C#List<int> numbers = new List<int> { 5, 2, 8, 1, 3 };
numbers.Sort();
この方法はシンプルで、数値や文字列の昇順ソートに向いています。
ただし、元のList自体が変更される点には注意が必要です。
元の順番を残したい場合は、コピーを作るかLINQを使いましょう。
8-2. 配列を並び替えたいならArray.Sort()
配列を並び替えたい場合は、Array.Sort()を使います。
C#int[] numbers = { 5, 2, 8, 1, 3 };
Array.Sort(numbers);
配列の中身を直接変更して昇順に並び替えます。
降順にしたい場合は、Array.Reverse()を組み合わせます。
C#Array.Sort(numbers);
Array.Reverse(numbers);
配列を扱っている場合は、まずArray.Sort()を検討するとよいでしょう。
8-3. 元データを残したいならLINQのOrderBy()
元データを変更したくない場合は、LINQのOrderBy()を使うのがおすすめです。
C#List<int> sortedNumbers = numbers.OrderBy(x => x).ToList();
OrderBy()は元のデータを変更せず、並び替えた結果を新しく返します。
降順の場合は、OrderByDescending()を使います。
C#List<int> sortedNumbers = numbers.OrderByDescending(x => x).ToList();
元の順番を残したまま表示だけ並び替えたい場合や、加工後のデータだけを別に使いたい場合に便利です。
8-4. 複数条件で並び替えたいならOrderBy()とThenBy()
複数条件でソートしたい場合は、LINQのOrderBy()とThenBy()を使います。
C#List<Person> sortedPeople = people
.OrderBy(p => p.Age)
.ThenBy(p => p.Name)
.ToList();
この例では、まず年齢順に並び替え、同じ年齢の場合は名前順に並び替えています。
降順を使いたい場合は、OrderByDescending()やThenByDescending()を組み合わせます。
C#List<Student> sortedStudents = students
.OrderByDescending(s => s.Score)
.ThenBy(s => s.Name)
.ToList();
複数条件のソートは、List.Sort()よりもLINQのほうが読みやすく書けることが多いです。
8-5. 独自ルールで並び替えたいならComparisonやIComparer
独自ルールで並び替えたい場合は、ComparisonやIComparerを使います。
ラムダ式で簡単に書くなら、Comparisonが便利です。
C#words.Sort((a, b) => a.Length.CompareTo(b.Length));
比較ルールを再利用したい場合や、処理が複雑な場合はIComparerを使います。
C#class LengthComparer : IComparer<string>
{
public int Compare(string x, string y)
{
return x.Length.CompareTo(y.Length);
}
}
単純なソートならSort()やOrderBy()、複雑なソートならComparisonやIComparerと考えると選びやすくなります。
9. C#のソートに関するよくある質問
ここでは、C#のソートについて初心者が疑問に感じやすいポイントをQ&A形式で解説します。
9-1. C#で降順ソートするにはどうすればいい?
C#で降順ソートする方法はいくつかあります。
Listの場合は、Sort()で昇順にしたあとReverse()を使えます。
C#numbers.Sort();
numbers.Reverse();
LINQを使う場合は、OrderByDescending()を使います。
C#List<int> sortedNumbers = numbers
.OrderByDescending(x => x)
.ToList();
配列の場合は、Array.Sort()とArray.Reverse()を組み合わせます。
C#Array.Sort(numbers);
Array.Reverse(numbers);
元データを変更してよいならSort()やArray.Sort()、元データを残したいならOrderByDescending()がおすすめです。
9-2. List.Sort()とOrderBy()はどちらが初心者向け?
単純にListを昇順に並び替えるだけなら、List.Sort()のほうが簡単です。
C#numbers.Sort();
ただし、List.Sort()は元のリストを直接変更します。
一方、LINQのOrderBy()は元データを変更せず、並び替えた結果を返します。
C#List<int> sortedNumbers = numbers.OrderBy(x => x).ToList();
初心者には、目的によって使い分けることをおすすめします。
Listをそのまま変更したいならSort()、元データを残したいならOrderBy()を使いましょう。
9-3. 文字列を五十音順にソートできる?
C#でも日本語の文字列をソートすることはできます。
C#List<string> names = new List<string>
{
"たろう",
"はなこ",
"あいこ"
};
names.Sort();
ただし、日本語の五十音順を厳密に扱いたい場合は注意が必要です。
漢字、ひらがな、カタカナ、濁点、半角・全角などが混ざると、期待どおりの順番にならない場合があります。
より正確に五十音順で並べたい場合は、ふりがな用のプロパティを用意して、その値でソートする方法がよく使われます。
C#class Person
{
public string Name { get; set; }
public string Kana { get; set; }
}
C#List<Person> sortedPeople = people
.OrderBy(p => p.Kana)
.ToList();
日本語名を扱うシステムでは、表示名ではなく「ふりがな」や「読み仮名」を基準にソートすると安定しやすくなります。
9-4. オブジェクトのListを特定のプロパティでソートするには?
オブジェクトのListを特定のプロパティでソートするには、LINQのOrderBy()を使うのが簡単です。
たとえば、年齢順に並び替える場合は次のように書きます。
C#List<Person> sortedPeople = people
.OrderBy(p => p.Age)
.ToList();
名前順に並び替える場合は、次のように書きます。
C#List<Person> sortedPeople = people
.OrderBy(p => p.Name)
.ToList();
降順にしたい場合は、OrderByDescending()を使います。
C#List<Person> sortedPeople = people
.OrderByDescending(p => p.Age)
.ToList();
複数条件を指定したい場合は、ThenBy()を組み合わせます。
C#List<Person> sortedPeople = people
.OrderBy(p => p.Age)
.ThenBy(p => p.Name)
.ToList();
オブジェクトのソートでは、「どのプロパティを基準にするか」を指定することが重要です。
9-5. ソート後に元の順番へ戻すことはできる?
List.Sort()やArray.Sort()で直接並び替えた場合、元の順番は自動では保存されません。
そのため、ソート後に元の順番へ戻したい場合は、ソート前にコピーを作っておく必要があります。
C#List<int> numbers = new List<int> { 5, 2, 8, 1, 3 };
List<int> originalNumbers = new List<int>(numbers);
numbers.Sort();
// 元に戻す
numbers = new List<int>(originalNumbers);
LINQのOrderBy()を使えば、元データは変更されないため、元の順番をそのまま残せます。
C#List<int> sortedNumbers = numbers.OrderBy(x => x).ToList();
元の順番が必要になる場合は、Sort()で直接変更する前にコピーを作るか、LINQを使うようにしましょう。
まとめ
C#でソートを行う方法には、List.Sort()、Array.Sort()、LINQのOrderBy()やOrderByDescending()などがあります。
Listを直接並び替えたい場合は、List.Sort()を使います。
C#numbers.Sort();
配列を直接並び替えたい場合は、Array.Sort()を使います。
C#Array.Sort(numbers);
元データを変更せずに並び替えたい場合は、LINQのOrderBy()を使います。
C#List<int> sortedNumbers = numbers.OrderBy(x => x).ToList();
降順にしたい場合は、OrderByDescending()やReverse()を使います。
C#List<int> sortedNumbers = numbers.OrderByDescending(x => x).ToList();
オブジェクトのリストをソートする場合は、プロパティを指定します。
C#List<Person> sortedPeople = people.OrderBy(p => p.Age).ToList();
複数条件でソートしたい場合は、ThenBy()やThenByDescending()を組み合わせます。
C#List<Person> sortedPeople = people
.OrderBy(p => p.Age)
.ThenBy(p => p.Name)
.ToList();
C#のソートで大切なのは、元データを変更するかどうかを意識することです。
List.Sort()とArray.Sort()は元データを直接変更します。一方、LINQのOrderBy()は元データを変更せず、並び替えた結果を返します。
初心者のうちは、次のように覚えておくと迷いにくくなります。
| 目的 | おすすめの方法 |
|---|---|
| Listを直接並び替える | List.Sort() |
| 配列を直接並び替える | Array.Sort() |
| 元データを残す | OrderBy() |
| 降順にする | OrderByDescending() |
| 複数条件で並び替える | OrderBy() + ThenBy() |
| 独自ルールで並び替える | ComparisonまたはIComparer |
C#のソートは、最初はメソッドの違いがわかりにくいかもしれません。しかし、Sort()は直接変更、OrderBy()は新しい結果を返す、という違いを理解すれば、使い分けは難しくありません。
一覧表示やランキング、検索結果、日付順の表示など、ソートは実務でも頻繁に使う基本処理です。この記事で紹介したサンプルコードを参考に、まずは数値や文字列のソートから試してみましょう。

