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()変更されない
独自ルールで並び替えたいComparisonIComparer方法による

初心者のうちは、まず次のように覚えるとよいでしょう。

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

独自ルールで並び替えたい場合は、ComparisonIComparerを使います。

ラムダ式で簡単に書くなら、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()、複雑なソートならComparisonIComparerと考えると選びやすくなります。

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()は新しい結果を返す、という違いを理解すれば、使い分けは難しくありません。

一覧表示やランキング、検索結果、日付順の表示など、ソートは実務でも頻繁に使う基本処理です。この記事で紹介したサンプルコードを参考に、まずは数値や文字列のソートから試してみましょう。