C# 独自クラスの配列や List<T> を任意にソートする

独自に定義したクラスを格納した配列や List<T> を任意にソートする方法について説明します。

.NET Framework 1.0 ではソート用のメソッドを用意していましたが、.NET Framework 2.0 からは匿名メソッドを使用することができるようになりました。さらに.NET Framework 3.0 以降ではラムダ式を使用してシンプルに記載することができるようになりました。

ここではラムダ式を使用して、独自クラスの配列やList<T> を任意の方法でソートしてみます。

まずは、独自に定義したクラスですが、ここでは単純に ID と Name をプロパティに持つクラスを使用します。

    public class Employee
    {
        public int ID { getset; }
        public string Name { getset; }
    }

適当なデータを作成して、それぞれIDや名前の長さでソートを行っていますが、1行で書く事ができます。

        // ~ 適当なデータをList<T>と配列に格納する ~ 
        List<Employee> employeeList = new List<Employee>();
        employeeList.Add(new Employee(2, "William Henry Gates"));
        employeeList.Add(new Employee(3, "Steven Paul Jobs"));
        employeeList.Add(new Employee(1, "Lawrence Edward Larry Page"));
         
        Employee[] employeeArray = employeeList.ToArray();
        
        // リストをID順でソートする
        employeeList.Sort((a, b) => a.ID - b.ID);
         
        // 結果、下記の順にソートされます
        // ID=1 Name=Lawrence Edward Larry Page
        // ID=2 Name=William Henry Gates
        // ID=3 Name=Steven Paul Jobs
         
        // 配列を名前の長さが短い順でソートする
        Array.Sort(employeeArray, (a, b) => a.Name.Length - b.Name.Length);
         
        // 結果、下記の順にソートされます
        // ID=3 Name=Steven Paul Jobs
        // ID=2 Name=William Henry Gates
        // ID=1 Name=Lawrence Edward Larry Page

ラムダ式の部分が良く分からない方の為に、ラムダ式を使わない書き方も紹介します。

まず、比較用のメソッドを用意します。比較用のメソッドは戻り値をint型にして、比較する型2つを引数にします(ここでは引数をそれぞれ a, b としています)。戻り値は下の表を参考にしてください。

  • 負の値 : インスタンス a は、並べ替え順序において b の前になります。
  • 0 : インスタンス a は、並べ替え順序で、b と同じ位置に出現します。
  • 正の値 : インスタンス a は、並べ替え順序において b の後になります。
        /// <summary>
        /// ID順で比較
        /// </summary>
        private static int CompareByID(Employee a, Employee b)
        {
            return a.ID - b.ID;
        }

上で作成した比較用のメソッドをSortの引数に指定します。

        // リストをID順でソートする
        employeeList.Sort(CompareByID);

ラムダ式の部分はこれと全く等価のコードになります。ソースコード中に何度も同じ比較を行う場合は比較用のメソッドを用意し、1度しか使用されない場合はラムダ式を使って簡潔に記載するのが良いと思われます。

参考:List<T> 任意の項目を削除・抽出・変換する
使用環境: Visual Studio 2010 .NET Framework 3.0 以降

C# メニューリスト