Listのソート (IComparable を用いたカスタムソート) - C#

IComparable を用いたListのカスタムソートのコードを紹介します。

概要

クラスオブジェクト(List<T>)のリストをソートする場合、オブジェクトの大小関係を判定する必要があります。 IComparable インターフェイスを利用して、CompareTo メソッドを実装すると、オブジェクトの大小関係を判定するロジックを実装でき、 Sortメソッドでオブジェクトのリストをソートできます。
この記事では、IComparable インターフェイスとCompareToメソッドの実装手順を紹介します。

プログラム例

Windows Formアプリケーションを作成し、以下のコードを記述します。

UI

下図のフォームを作成します。ボタンとテキストボックスを配置します。

コード

以下のコードを記述します。
namespace ListSortComparable
{
  public partial class FormMain : Form
  {
    public FormMain()
    {
      InitializeComponent();
    }

    private void button1_Click(object sender, EventArgs e)
    {
      List<MyItem> mlist = new List<MyItem>();
      mlist.Add(new MyItem() { id = 2, itemname = "らくだキャラメル", price = 80, stocks = 45, category = 2 });
      mlist.Add(new MyItem() { id = 1, itemname = "ぺんぎんクッキー", price = 160, stocks = 25, category = 1 });
      mlist.Add(new MyItem() { id = 8, itemname = "ももんがマシュマロ", price = 100, stocks = 32, category = 1 });
      mlist.Add(new MyItem() { id = 3, itemname = "しろくまアイス", price = 280, stocks = 12, category = 3 });
      mlist.Add(new MyItem() { id = 4, itemname = "かるがもサブレ", price = 140, stocks = 6, category = 1 });
      mlist.Add(new MyItem() { id = 6, itemname = "きつつきキャンディ", price = 50, stocks = 18, category = 2 });
      mlist.Add(new MyItem() { id = 5, itemname = "くじらロールケーキ", price = 680, stocks = 4, category = 1 });
      mlist.Add(new MyItem() { id = 7, itemname = "あるぱかグミ", price = 20, stocks = 28, category = 2 });

      for (int i = 0; i < mlist.Count; i++) {
        textBox1.Text += string.Format("ID:{0:d}  name:{1} price:{2:d}  stocks:{3:d}  category:{4:d}\r\n",
          mlist[i].id, mlist[i].itemname, mlist[i].price, mlist[i].stocks, mlist[i].category);
      }
      textBox1.Text += "------\r\n\r\n";
      mlist.Sort();
      for (int i = 0; i < mlist.Count; i++) {
        textBox1.Text += string.Format("ID:{0:d}  name:{1} price:{2:d}  stocks:{3:d}  category:{4:d}\r\n",
          mlist[i].id, mlist[i].itemname, mlist[i].price, mlist[i].stocks, mlist[i].category);
      }

    }
  }
}
MyItem.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ListSortComparable
{
  public class MyItem: IComparable<MyItem>
  {
    public int id;
    public string itemname="";
    public int price;
    public int stocks;
    public int category;

    public int CompareTo(MyItem? other)
    {
      if (other != null) {
        if (id == other.id) {
          return 0;
        }
        else if (id < other.id) {
          return -1;
        }
        else {
          return 1;
        }
      }
      else {
        return 0;
      }
    }
  }
}

解説

MyItem.cs

カスタムのソートのロジックを実装したMyItemクラスを作成します。
カスタムのソートロジックのCompareTo() メソッドをオーバーライドするため、 作成するクラスは、IComparable<MyItem>インターフェイスを実装します。
public class MyItem: IComparable<MyItem>

クラスにCompareToメソッドをオーバーライドして実装します。
今回の例では、メンバ変数idの値の大小で2つのMyItemオブジェクトの大小を決定するロジックを実装しています。
    public int CompareTo(MyItem? other)
    {
      if (other != null) {
        if (id == other.id) {
          return 0;
        }
        else if (id < other.id) {
          return -1;
        }
        else {
          return 1;
        }
      }
      else {
        return 0;
      }
    }

フォーム

List<MyItem> オブジェクトを作成し、MyItemオブジェクトを作成し、値を設定しリストに追加して元データを作成します。
      List<MyItem> mlist = new List<MyItem>();
      mlist.Add(new MyItem() { id = 2, itemname = "らくだキャラメル", price = 80, stocks = 45, category = 2 });
      mlist.Add(new MyItem() { id = 1, itemname = "ぺんぎんクッキー", price = 160, stocks = 25, category = 1 });
      mlist.Add(new MyItem() { id = 8, itemname = "ももんがマシュマロ", price = 100, stocks = 32, category = 1 });
      mlist.Add(new MyItem() { id = 3, itemname = "しろくまアイス", price = 280, stocks = 12, category = 3 });
      mlist.Add(new MyItem() { id = 4, itemname = "かるがもサブレ", price = 140, stocks = 6, category = 1 });
      mlist.Add(new MyItem() { id = 6, itemname = "きつつきキャンディ", price = 50, stocks = 18, category = 2 });
      mlist.Add(new MyItem() { id = 5, itemname = "くじらロールケーキ", price = 680, stocks = 4, category = 1 });
      mlist.Add(new MyItem() { id = 7, itemname = "あるぱかグミ", price = 20, stocks = 28, category = 2 });

List<MyItem> オブジェクトを順にテキストボックスに表示します。
      for (int i = 0; i < mlist.Count; i++) {
        textBox1.Text += string.Format("ID:{0:d}  name:{1} price:{2:d}  stocks:{3:d}  category:{4:d}\r\n",
          mlist[i].id, mlist[i].itemname, mlist[i].price, mlist[i].stocks, mlist[i].category);
      }
      textBox1.Text += "------\r\n\r\n";

Sort()メソッドを実行して、リストをソートします。
      mlist.Sort();

ソート後のリストの値をテキストボックスに表示します。
      for (int i = 0; i < mlist.Count; i++) {
        textBox1.Text += string.Format("ID:{0:d}  name:{1} price:{2:d}  stocks:{3:d}  category:{4:d}\r\n",
          mlist[i].id, mlist[i].itemname, mlist[i].price, mlist[i].stocks, mlist[i].category);
      }

実行結果

プロジェクトを実行します。下図のウィンドウが表示されます。


[button1]をクリックします。テキストボックスに下図の結果が表示されます。
前半の出力は、リストに追加した順番に値が表示されていますが、 後半の出力は、ID値が昇順に表示され、Sortメソッドの呼び出しにより、 MyItemオブジェクトのCompareTo()メソッドが実行され、IDの値順にソートされた動作が確認できます。


著者
iPentecのメインプログラマー
C#, ASP.NET の開発がメイン、少し前まではDelphiを愛用
掲載日: 2023-12-27
iPentec all rights reserverd.