Rainbow Engine

IT技術を分かりやすく簡潔にまとめることによる学習の効率化、また日常の気付きを記録に残すことを目指します。

C#

C#のIComparableの実装方法+IComparerとの違いについて

投稿日:2021年2月2日 更新日:

<目次>

(1) C#のIComparableの実装方法+IComparerとの違いについて
 (1-1) IComparableの概要とIComparableとの違い
 (1-2) STEP0:比較をするクラスの定義
 (1-3) STEP1:IComparableインターフェイスの実装
 (1-4) STEP2:Compareメソッドの実装
 (1-5) STEP3:ソートの実行
 (1-6) サンプルプログラム

(1) C#のIComparableの実装方法+IComparerとの違いについて

(1-1) IComparableの概要とIComparableとの違い

「IComparable」は、オブジェクト同士の比較を行うためのメソッドを公開したインターフェイスです。似た名前のインターフェイスで「IComparer」がありますが、違いとして「IComparable」は自分と同じ型のオブジェクトを受け取って比較する(自分と相手の比較)なのに対して、「IComparer」は同じ型の異なるオブジェクトを比較する(二者の比較)という点で異なります。

もう少しイメージが湧きやすいように、プログラムの骨組みで比較すると、次のようなイメージです。

(図111)IComparableは「自クラス」と同型の「相手クラス」との比較

(図112)IComparerは「2つの同型の異なるクラス」同士の比較

目次にもどる

(1-2) STEP0:比較をするクラスの定義

まずはベースとなる、比較を行いたいクラスを作ります。

次の例は「Big4Players」という、男子テニスの「Big4」と呼ばれる選手(フェデラー、ナダル、ジョコビッチ、マレー)の「名前」(Name)と「グランドスラム優勝回数」(GrandSlamWin)と保持するためのクラスです(テニスネタでスミマセン・・💦)。

(STEP0)

    // STEP0:比較をするクラスの定義
    class Big4Players
    {
        // メンバ変数
        public string Name { get; set; }
        public int GrandSlamWin { get; set; }
    }

(参考)
「{ get; set; }」は「プロパティ」と呼ばれ、メンバ変数のゲッター(取得)、セッター(更新)のメソッドを定義しています。

目次にもどる

(1-3) STEP1:IComparableインターフェイスの実装

次に、定義したクラスが「IComparable」インターフェイスを実装するように改修します。

(STEP1)

    // STEP0:比較をするクラスの定義
    // STEP1:IComparableインターフェイスの実装
    class Big4Players : IComparable<Big4Players>
    {
        // メンバ変数
        public string Name { get; set; }
        public int GrandSlamWin { get; set; }

    }

目次にもどる

(1-4) STEP2:CompareToメソッドの実装

次はいよいよ「CompareTo」メソッドを実装します。

ちなみにIComparerの時の比較メソッドは「Compare」という名前でしたが、今回は「自分」と「相手」を比較するので「CompareTo」(~と比べる)の方が確かに名前としてしっくり来ます。

このメソッドは自身と同型の別インスタンスを比較し、その大小をint型で返却します。戻り値の値はソートを昇順でしたいのか?降順でしたいのか?によって次のように定義します。

 

(1)昇順にソートする場合「自身の方が大きい=1、自身の方が小さい=-1、同じ=0」
(2)降順にソートする場合「自身の方が大きい=-1、自身の方が小さい=1、同じ=0」

今回は優勝回数が多い順に並べるので降順ソートで実装しています。

(STEP2)

    // STEP0:比較をするクラスの定義
    // STEP1:IComparableインターフェイスの実装
    class Big4Players : IComparable
    {
        // メンバ変数
        public string Name { get; set; }
        public int GrandSlamWin { get; set; }

        // STEP2:CompareToメソッドの実装
        public int CompareTo(Big4Players other)
        {
            // 降順にソートしたいので、this(自分) < other(相手) に1を割り当て
            if (this.GrandSlamWin < other.GrandSlamWin)
            {
                return 1;
            }
            // 降順にソートしたいので、this(自分) > other(相手) に-1を割り当て
            else if (this.GrandSlamWin > other.GrandSlamWin)
            {
                return -1;
            }
            else
            {
                return 0;
            }
        }
        // コンソール出力用のメソッド
        public override string ToString()
        {
            return $"{this.Name} {this.GrandSlamWin}";
        }
    }

目次にもどる

(1-5) STEP3:ソートの実行

ここまで来たら実際にソートしたいListを定義して、要素を追加してSort()メソッドを実行する事でソートが行えます。Sortメソッドの引数には先ほど定義したBig4Comparerクラスのインスタンスを与えます。

(STEP3)

    class Program
    {
        static void Main(string[] args)
        {
            // var(暗黙型)でBig4Players2のリストを定義
            var big4 = new List<Big4Players>();
            // リストに要素を追加
            big4.Add(new Big4Players() { Name = "Roger Federer", GrandSlamWin = 20 });
            big4.Add(new Big4Players() { Name = "Rafale Nadal", GrandSlamWin = 20 });
            big4.Add(new Big4Players() { Name = "Novak Djokovic", GrandSlamWin = 17 });
            big4.Add(new Big4Players() { Name = "Andy Murray", GrandSlamWin = 3 });
            // ソートの実行(内部的にCompareToメソッドが使われる)
            big4.Sort();
            // コンソール出力
            big4.ForEach(big4player => Console.WriteLine(big4player));
        }
    }

目次にもどる

(1-6) サンプルプログラム

上記STEP0~STEP3までを繋げて、main文などを追記して実行可能にしたものを掲載します。

プログラム中で登場するvar(暗黙型)については別記事でも説明しているため、興味ある方は併せてご覧いただけたらと思います。

参考①:C#のvarの使いどころは?初めての方に向けてサンプルプログラムを使ってご紹介
参考②:C#のvarとは?型を調べる方法や制約事項についてもご紹介

(サンプルプログラム)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace IComparerTest
{
    // STEP0:比較をするクラスの定義
    // STEP1:IComparableインターフェイスの実装
    class Big4Players : IComparable<Big4Players>
    {
        // メンバ変数
        public string Name { get; set; }
        public int GrandSlamWin { get; set; }

        // STEP2:CompareToメソッドの実装
        public int CompareTo(Big4Players other)
        {
            // 降順にソートしたいので、this(自分) < other(相手) に1を割り当て
            if (this.GrandSlamWin < other.GrandSlamWin)
            {
                return 1;
            }
            // 降順にソートしたいので、this(自分) > other(相手) に-1を割り当て
            else if (this.GrandSlamWin > other.GrandSlamWin)
            {
                return -1;
            }
            else
            {
                return 0;
            }
        }

        // コンソール出力用のメソッド
        public override string ToString()
        {
            return $"{this.Name} {this.GrandSlamWin}";
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            // var(暗黙型)でBig4Players2のリストを定義
            var big4 = new List<Big4Players>();
            // リストに要素を追加
            big4.Add(new Big4Players() { Name = "Roger Federer", GrandSlamWin = 20 });
            big4.Add(new Big4Players() { Name = "Rafale Nadal", GrandSlamWin = 20 });
            big4.Add(new Big4Players() { Name = "Novak Djokovic", GrandSlamWin = 17 });
            big4.Add(new Big4Players() { Name = "Andy Murray", GrandSlamWin = 3 });
            // ソートの実行(内部的にCompareToメソッドが使われる)
            big4.Sort();
            // コンソール出力
            big4.ForEach(big4player => Console.WriteLine(big4player));
        }
    }
}

(図161)実行結果
狙った通り降順にソートされています(20⇒20⇒17⇒3)

目次にもどる

Adsense審査用広告コード


Adsense審査用広告コード


-C#

執筆者:


comment

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

関連記事

C#のvarの使いどころは?初めての方に向けてサンプルプログラムを使ってご紹介

<目次> (1) C#のvarの使いどころは?初めての方に向けてサンプルプログラムを使ってご紹介  (1-1) ArrayListに異なるデータ型が混在しているパターン  (1-2) LINQのクエリ …

C#のlockとは?意味や使い方とサンプルプログラムをご紹介

  <目次> (1) C#のlockとは?意味や使い方とサンプルプログラムをご紹介  (1-1) 概要  (1-2) 構文  (1-3) サンプルプログラム  (1-4) lockステートメ …

ASP.NET MVCのRouteConfigを追加する方法を2つご紹介

  <目次> (1) ASP.NET MVCのRouteConfigを追加する方法を2つご紹介  (1-1) やりたい事の整理  (1-2) 方法1:通常のルーティング  (1-3) 方法2 …

C#のintに?「はてな」(question mark)が付いている意味について

<目次> (1) C#のintに?「はてな」(question mark)が付いている意味について  (1-1) 「int?」とは?  (1-2) 「int?」の型について  (1-3) 「int?」 …

BundleConfig.csの設定および記述方法について

  <目次> (1) BundleConfig.csの設定および記述方法について  (1-1) BundleConfig.csの設定および記述方法について  (1-2) BundleConf …

  • English (United States)
  • 日本語
Top