C#でプログラムを組んでいると、データの集合を特定のルールに従って並び替えたい場面が頻繁に訪れます。
ランキングの作成、アルファベット順の顧客リスト、あるいは最新日付順のログ表示など、ソート処理はアプリケーション開発の根幹をなす技術です。
Array.Sort と OrderBy はどう使い分けるの?」「降順にするには?」「2次元配列を特定の列で並び替えたい」といった疑問を抱える開発者も少なくありません。この記事では、C#における配列ソートの基本から、ラムダ式を用いたカスタムソート、実務で役立つ複数条件の指定方法まで、具体的なサンプルコードを交えて詳しく解説します。
![]() 執筆者:マヒロ |
|
- OS:Windows 11 / macOS Sequoia
- IDE:Visual Studio / VS Code / IntelliJ IDEA
- その他:Chrome DevTools / 各言語最新安定版
※本メディアでは、上記環境にてコードの動作と情報の正確性を検証済みです。
Array.SortとLINQ(OrderBy)による基本ソート
C#で配列をソートする手法は、大きく分けて「元の配列を直接書き換える方法(破壊的)」と「並び替えた新しいデータを取得する方法(非破壊的)」の2つがあります。
用途に合わせて最適な手法を選択できるよう、まずはそれぞれの基本的な書き方を確認しましょう。
Array.Sortで配列を直接ソートする
最も基本的なのが、System 名前空間にある Array.Sort メソッドを使用する方法です。
using System;
class Program
{
static void Main()
{
int[] numbers = { 5, 2, 8, 1, 9 };
// 配列を昇順にソート(元の配列が書き換わります)
Array.Sort(numbers);
Console.WriteLine("昇順ソート後:");
Console.WriteLine(string.Join(", ", numbers));
}
}
実行結果
昇順ソート後: 1, 2, 5, 8, 9
このソースコードは、整数型の配列を昇順に並び替える最もシンプルな実装例です。
Array.Sort メソッドを呼び出すと、引数に渡した numbers 配列自体の並び順が内部で書き換えられます。これを「破壊的ソート」と呼びます。
この手法は、追加の作業メモリをほぼ消費しないため、大規模な配列を扱う際にメモリ効率の面で有利になることが多いです。
データの原本を保持しておく必要がなく、パフォーマンスを優先したい場合に適した手法といえるでしょう。
OrderBy(LINQ)を使ってソートされた結果を取得する
元の配列を汚したくない場合や、より直感的に記述したい場合は、LINQの OrderBy メソッドが推奨されます。
using System;
using System.Linq; // LINQを使用するために必要
class Program
{
static void Main()
{
string[] fruits = { "Orange", "Apple", "Banana" };
// LINQを使ってソートされた列挙を取得
// ToArray() を呼んだ時点で新しい配列が生成されます
var sortedFruits = fruits.OrderBy(f => f).ToArray();
Console.WriteLine("ソートされた結果:");
Console.WriteLine(string.Join(", ", sortedFruits));
Console.WriteLine($"元の配列の先頭: {fruits[0]}");
}
}
実行結果
ソートされた結果: Apple, Banana, Orange 元の配列の先頭: Orange
この処理の流れを紐解いていきましょう。
拡張メソッド OrderBy は、元の配列には一切変更を加えず、ソート済みのシーケンス(IEnumerable)を返します。
注意点として、OrderBy 自体は遅延実行されるため、このコードのように ToArray() や ToList() を呼び出したタイミングで初めてソート処理が行われ、新しい配列(非破壊的な結果)がメモリ上に生成されます。
関数型プログラミングのような安全な実装を行いたい場合に最適な選択肢となります。
配列を降順にソートする具体的な方法
データを大きい順、あるいは日付の新しい順に並べたい「降順ソート」は、検索ニーズが非常に高い操作です。
C#では、メソッド一つで簡単に切り替えることが可能です。
ここでは、サジェストキーワードでも注目されている「c# 配列 ソート 降順」の具体的な実装を2パターン紹介します。
OrderByDescendingを活用した降順ソート
LINQを使用している場合は、OrderByDescending メソッドに差し替えるだけで完了します。
using System;
using System.Linq;
class Program
{
static void Main()
{
double[] prices = { 1500.5, 300.0, 5000.0, 120.5 };
// 値が大きい順(降順)にソート
var descendingPrices = prices.OrderByDescending(p => p).ToArray();
Console.WriteLine("降順ソートの結果:");
foreach (var price in descendingPrices)
{
Console.WriteLine(price);
}
}
}
実行結果
降順ソートの結果: 5000 1500.5 300 120.5
このコードでは、数値配列に対して OrderByDescending を適用しています。
昇順の OrderBy と対になるメソッドであり、ラムダ式で指定した基準に基づいて「降順」の結果を返します。
読み取り専用のデータを扱う際や、Web APIのレスポンスを整形する際など、モダンな開発現場ではこの手法が最も一般的です。
Array.Reverseによる反転処理
Array.Sort で昇順にした後、全体をひっくり返すことで降順を実現することも可能です。
int[] data = { 10, 50, 30 };
Array.Sort(data); // 10, 30, 50 になる
Array.Reverse(data); // 50, 30, 10 になる
この実装は、まず配列を小さい順に並び替え、その後に Array.Reverse メソッドを呼び出して順序を逆転させています。
LINQを使えない制約のある環境や、既存の配列オブジェクトをそのまま使いまわしたい内部処理などで利用されることがあります。
文字列のソートと自然順ソートの実現
文字列の配列をソートする場合、標準では現在の実行環境の設定に基づいた「カルチャ依存の文字列比較(人間向けの辞書順)」が行われます。
実務で重要となる「自然順ソート」の考え方についても触れていきましょう。
標準的な文字列ソート
string[] files = { "file10.txt", "file1.txt", "file2.txt" };
Array.Sort(files);
// 結果: file1.txt, file10.txt, file2.txt
通常のソートでは "1" の次に "10" が来て、その後に "2" が来ます。
これは各文字の並び順で比較が行われるためですが、ユーザー向けに表示する際は不自然です。
これを解決するのが自然順ソートのテクニックです。
自然順ソート(数値の大小を考慮)の実装
自然順(1, 2, 10の順)を実現するには、Windowsのシステム関数を呼び出すのが一般的ですが、この方法は Windows 環境限定であることに注意してください(LinuxやmacOS上の .NET では動作しません)。
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices; // Windows API用
class NaturalStringComparer : IComparer<string>
{
// Windowsの自然順比較関数をインポート(Windows専用)
[DllImport("shlwapi.dll", CharSet = CharSet.Unicode)]
private static extern int StrCmpLogicalW(string psz1, string psz2);
public int Compare(string x, string y) => StrCmpLogicalW(x, y);
}
class Program
{
static void Main()
{
string[] files = { "file10.txt", "file1.txt", "file2.txt" };
// 自作の比較クラスを指定してソート
Array.Sort(files, new NaturalStringComparer());
Console.WriteLine("自然順ソート後:");
Console.WriteLine(string.Join(", ", files));
}
}
実行結果
自然順ソート後: file1.txt, file2.txt, file10.txt
このソースコードでは、Windowsの shlwapi.dll に含まれる StrCmpLogicalW 関数を呼び出しており、これが文字列内の数字を数値として解釈してくれます。
クロスプラットフォーム環境(Dockerなど)で同様の機能が必要な場合は、正規表現を組み込んだ独自の比較ロジックを作成する必要があります。
2次元配列や複雑な複数条件でのソート(ラムダ式の活用)
実務では単一の配列よりも、行と列を持つ「2次元配列」や「オブジェクトのリスト」を扱う機会が圧倒的に多いでしょう。
これらについて解説していきます。
2次元配列(ジャグ配列)の特定要素によるソート
C#の厳密な2次元配列(int[,])は構造上ソートの実装が非常に煩雑になるため、実務では「配列の配列」であるジャグ配列(int[][])や List<T> が選ばれることが一般的です。
using System;
using System.Linq;
class Program
{
static void Main()
{
// ユーザーIDとスコアのセット
int[][] data = new int[][]
{
new int[] { 1, 80 },
new int[] { 2, 100 },
new int[] { 3, 50 },
new int[] { 4, 80 }
};
// スコア(インデックス1)の降順でソート
var sortedData = data.OrderByDescending(row => row[1])
.ThenBy(row => row[0]) // スコアが同じならID順
.ToArray();
Console.WriteLine("スコア順(同点ならID順):");
foreach (var row in sortedData)
{
Console.WriteLine($"ID: {row[0]}, Score: {row[1]}");
}
}
}
実行結果
スコア順(同点ならID順): ID: 2, Score: 100 ID: 1, Score: 80 ID: 4, Score: 80 ID: 3, Score: 50
このプログラムでは、OrderByDescending(row => row[1]) によってまず「スコア」を基準に並び替えます。
さらに重要なのが ThenBy メソッドの存在です。これを使うことで、「スコアが同じ(80点)だった場合、次はIDで昇順にする」という複数条件ソートが実現できます。
クラスや構造体の要素を指定してソートする
// List<User> を年齢順にソートする例
List<User> userList = GetUsers();
userList.Sort((a, b) => a.Age.CompareTo(b.Age));
この記述は、List<T>.Sort メソッドにラムダ式による比較ルールを渡しています。
リストそのものを書き換えるため、大規模なデータセットで追加メモリを抑えたい場合に重宝されるテクニックです。
C#のスキルを活かして年収を上げる方法
以上、C#で配列をソートする手法について解説してきました。
業務システム開発やアプリ開発、ゲーム開発において需要の高いC#を扱えるエンジニアは、転職によって数十万円の年収アップはザラで、100万円以上年収が上がることも珍しくありません。
なお、転職によって年収を上げたい場合は、エンジニア専門の転職エージェントサービスを利用するのが最適です。
転職エージェントも副業エージェントも、登録・利用は完全無料なので、どんな求人や副業案件があるのか気になる方は、気軽に利用してみるとよいでしょう。
| 年収アップにこだわりたい方 (平均アップ額138万円の実績) | テックゴー |
| 未経験・経験者問わず幅広く探したい方 | ユニゾンキャリア |
| 業界に精通した担当者に相談したい方 | キッカケエージェント |
| ゲーム業界への転職を志望する方 | ファミキャリ |
| エンジニア未経験からキャリアを築く方 | イーチキャリア |



