【C#】【Linq】OrderByメソッド、ThenByメソッド

■ OrderByに関するメソッド

OrderByメソッド、OrderByDescendingメソッド

 * Linqにおいて、昇順、降順の並び替えは、OrderByメソッド、OrderByDescendingメソッドで行う

ThenByメソッド、ThenByDescendingメソッド

 * OrderByメソッド、OrderByDescendingメソッドの後に、更に昇順、降順の並び替えを行いたい場合、
   ThenByメソッド、ThenByDescendingメソッドで行う

■ サンプル

using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;

namespace SampleForm
{
  public partial class Form1 : Form
  {
    public Form1()
    {
      InitializeComponent();
    }

    private void button1_Click(object sender, EventArgs e)
    {
      var people = new List<Person>()
      {
        new Person()
        {
          Id = "000", Age = 12, Name = "Mike", DeleteFlag = false,
          CreatedAt = DateTime.Parse("2019/04/11 12:21:22"),
          UpdatedAt = DateTime.Parse("1982/12/11"),
        },
        new Person()
        {
          Id = "001", Age = 12, Name = "Amy", DeleteFlag = false,
          CreatedAt = DateTime.Parse("2019/04/11 12:21:22"),
          UpdatedAt = DateTime.Parse("2019/04/11 22:21:22"),
        },
        new Person()
        {
          Id = "002", Age = 25, Name = "Bob", DeleteFlag = true,
          CreatedAt = DateTime.Parse("2019/04/12 12:21:22"),
          UpdatedAt = DateTime.Parse("2019/04/12 14:21:22"),
        },
        new Person()
        {
          Id = "003", Age = 91, Name = "Paul", DeleteFlag = false,
          CreatedAt = DateTime.Parse("2019/03/11 12:21:22"),
          UpdatedAt = DateTime.Parse("2019/03/11 13:21:22"),
        },
        new Person()
        {
          Id = "004", Age = 36, Name = "John", DeleteFlag = false,
          CreatedAt = DateTime.Parse("2019/04/13 12:21:22"),
          UpdatedAt = DateTime.Parse("1982/12/11 14:21:22"),
        },
        new Person()
        {
          Id = "005", Age = 9, Name = "Yohan", DeleteFlag = false,
          CreatedAt = DateTime.Parse("2019/02/13 12:21:22"),
          UpdatedAt = DateTime.Parse("2019/02/13 14:21:22"),
        },
        new Person()
        {
          Id = "006", Age = 56, Name = "Iwan", DeleteFlag = false,
          CreatedAt = DateTime.Parse("2019/01/12 12:21:22"),
          UpdatedAt = DateTime.Parse("2019/01/12 22:21:22"),
        },
        new Person()
        {
          Id = "007", Age = 71, Name = "Alice", DeleteFlag = false,
          CreatedAt = null,
          UpdatedAt = DateTime.Parse("2019/01/12 22:21:22"),
        },
        new Person()
        {
          Id = "008", Age = 35, Name = "Ken", DeleteFlag = false,
          CreatedAt = DateTime.Parse("2019/01/12 12:21:22"),
          UpdatedAt = null,
        },
        new Person()
        {
          Id = "009", Age = 26, Name = "Kevin", DeleteFlag = false,
          CreatedAt = null,
          UpdatedAt = null,
        },
        new Person()
        {
          Id = "010", Age = 16, Name = "Smith", DeleteFlag = false,
          CreatedAt = DateTime.Parse("2019/02/12 12:21:22"),
          UpdatedAt = DateTime.Parse("2019/02/12 22:21:22"),
        },
      };

      // ★ここ★
      var results = people.Where(person => !person.DeleteFlag)
            .OrderBy(person => person.Id)
            .ThenBy(person => person.Age)
            .ThenBy(person => person.Name);

      this.dataGridView1.DataSource = new BindingSource() {  DataSource = results };
    }
  }

  public class Person
  {
    public string Id { get; set; }
    public int Age { get; set; }
    public string Name { get; set; }
    public bool DeleteFlag { get; set; }
    public DateTime? CreatedAt { get; set; }
    public DateTime? UpdatedAt { get; set; }
  }
}

出力結果

000	12	Mike	False	2019/04/11 12:21	1982/12/11
001	12	Amy	False	2019/04/11 12:21	2019/04/11 22:21
003	91	Paul	False	2019/03/11 12:21	2019/03/11 13:21
004	36	John	False	2019/04/13 12:21	1982/12/11 14:21
005	9	Yohan	False	2019/02/13 12:21	2019/02/13 14:21
006	56	Iwan	False	2019/01/12 12:21	2019/01/12 22:21
007	71	Alice	False	        	2019/01/12 22:21
008	35	Ken	False	2019/01/12 12:21	
009	26	Kevin	False		
010	16	Smith	False	2019/02/12 12:21	2019/02/12 22:21

■ 補足:Null許容の並び替えについて

 * まずは、上記「サンプル」のデータを「// ★ここ★」を以下の行に置き換えてみる
OrderBy
// ★ここ★
var results = people.OrderBy(person => person.CreatedAt);

【出力結果】
CreatedAt
----------------
null
null
2019/01/12 12:21
2019/01/12 12:21
2019/02/12 12:21
2019/02/13 12:21
2019/03/11 12:21
2019/04/11 12:21
2019/04/11 12:21
2019/04/12 12:21
2019/04/13 12:21
OrderByDescending
// ★ここ★
var results = people.OrderByDescending(person => person.CreatedAt);

【出力結果】
CreatedAt
----------------
2019/04/13 12:21
2019/04/12 12:21
2019/04/11 12:21
2019/04/11 12:21
2019/03/11 12:21
2019/02/13 12:21
2019/02/12 12:21
2019/01/12 12:21
2019/01/12 12:21
null
null

逆に操作したい場合

つまり...

 * OrderBy で、nullを後にしたい
 * OrderByDescending で、nullを先にしたい

 => 「??」演算子(Null合体演算子 / null coalescing operator)を使う!

# 【復習】
# var result = x ?? y; // x が null の場合、y が代入される
OrderBy
// ★ここ★
var results = people.OrderBy(person => person.CreatedAt ?? DateTime.MinValue);

【出力結果】
null
null
2019/01/12 12:21
2019/01/12 12:21
2019/02/12 12:21
2019/02/13 12:21
2019/03/11 12:21
2019/04/11 12:21
2019/04/11 12:21
2019/04/12 12:21
2019/04/13 12:21
OrderByDescending
// ★ここ★
var results = people.OrderByDescending(person => person.CreatedAt ?? DateTime.MaxValue);

【出力結果】
CreatedAt
----------------
null
null
2019/04/13 12:21
2019/04/12 12:21
2019/04/11 12:21
2019/04/11 12:21
2019/03/11 12:21
2019/02/13 12:21
2019/02/12 12:21
2019/01/12 12:21
2019/01/12 12:21