for WPF developers
Home Profile Tips 全記事一覧

OrderBy 拡張メソッドで要素を昇順に並べ替える

(2017/03/08 18:37:15 created.)

(2017/03/13 8:41:20 modified.)

OrderBy 拡張メソッドを使えば簡単にコレクションを並べ替えることができます。例えば次のような Person クラスを例に OrderBy 拡張メソッドを使ってみましょう。

Person.cs
  1. namespace Tips_Linq
  2. {
  3.     using System;
  4.  
  5.     /// 
  6.     /// 人物データを表します。
  7.     /// 
  8.     public class Person
  9.     {
  10.         /// 
  11.         /// 氏名を取得または設定します。
  12.         /// 
  13.         public string Name { get; set; }
  14.  
  15.         /// 
  16.         /// 年齢を取得または設定します。
  17.         /// 
  18.         public int Age { get; set; }
  19.     }
  20. }
Program.cs
  1. namespace Tips_Linq
  2. {
  3.     using System;
  4.     using System.Collections.Generic;
  5.     using System.Linq;
  6.  
  7.     class Program
  8.     {
  9.         static void Main(string[] args)
  10.         {
  11.             var people = GetPeople();
  12.             foreach (var person in people)
  13.             {
  14.                 Console.WriteLine(person.Name + " (" + person.Age + ")");
  15.             }
  16.  
  17.             Console.WriteLine("年齢でソートします。");
  18.             var sortedPeople = people.OrderBy(x => x.Age);
  19.             foreach (var person in sortedPeople)
  20.             {
  21.                 Console.WriteLine(person.Name + " (" + person.Age + ")");
  22.             }
  23.  
  24.             Console.ReadKey();
  25.         }
  26.  
  27.         /// 
  28.         /// 人物コレクションの列挙子を取得します。
  29.         /// 
  30.         /// 
  31.         static IEnumerable<Person> GetPeople()
  32.         {
  33.             yield return new Person() { Name = "田中 淳平", Age = 37 };
  34.             yield return new Person() { Name = "鈴木 ほのか", Age = 26 };
  35.             yield return new Person() { Name = "小池 哲司", Age = 22 };
  36.             yield return new Person() { Name = "恩田 進", Age = 42 };
  37.             yield return new Person() { Name = "中津山 亜希子", Age = 20 };
  38.         }
  39.     }
  40. }


OrderBy 拡張メソッドの入力引数では、並べ替えに使用する値を指定します。上記の例では Person クラスの Age プロパティを指定しているため、年齢で並べ替えられることになります。

並べ替えをおこなう処理では大小比較をする必要があるため、例えば次のように Person クラスそのもので並べ変えようとすると、実行時に ArgumentException 例外が発生します。

Program.cs
  1.             Console.WriteLine("Person クラスでソートします?");
  2.             var sortedPeople = people.OrderBy(x => x);

カスタムクラスを比較するために、IComparable<T> インターフェースを実装した PersonComparer クラスを次のように定義します。

PersonComparer.cs
  1. namespace Tips_Linq
  2. {
  3.     using System.Collections.Generic;
  4.  
  5.     /// 
  6.     /// Person クラスに対する比較子を表します。
  7.     /// 
  8.     public class PersonComparer : IComparer<Person>
  9.     {
  10.         public static readonly PersonComparer AgeComparer = new PersonComparer();
  11.  
  12.         /// 
  13.         /// Person クラスを比較します。
  14.         /// 
  15.         /// "x">比較されるオブジェクトを指定します。
  16.         /// "y">比較するオブジェクトを指定します。
  17.         /// 比較結果を返します。
  18.         public int Compare(Person x, Person y)
  19.         {
  20.             return x.Age - y.Age;
  21.         }
  22.     }
  23. }

IComparable<T> インターフェースは Person クラスそのものに実装しても構いません。そうした場合は、冒頭のコードで実行できるようになります。Person クラスに実装することができない場合、PersonComparer クラスを外部で用意し、次のように OrderBy 拡張メソッドに第 2 引数として比較子を指定することで実行できるようになります。

Program.cs
  1.             Console.WriteLine("Person クラスでソートします。");
  2.             var sortedPeople = people.OrderBy(x => x, PersonComparer.AgeComparer);