がりらぼ

WindowsRuntimeの応援ブログ

C#の主要インターフェース解説:IComparable

IComparable

たとえば車クラス(Car)を作ったとして、これを一列にソートするとします。 自分で作った車クラスは、比較方法がないので優劣をつけることができず、1列に並べるにも規則性のある整列ができません。

そこで、自作クラスにIComparableインターフェースを実装することによって、「同じ自作クラス同士を比較できることを保証」します。

たとえばMyObjectという自作クラスを用意します。

public class MyObject
{
    public string hoge;
    public MyObject(string hoge)
    {
        this.hoge = hoge;
    }
    
}

このクラスはstring型の値を保持しますが比較方法が提供されていないのでMyObject同士で優劣をつけることができません。

そこで今回は保持しているstring型の文字列の、文字が長いほうが優秀というルールをつけます。

その比較ルールを提供するのがIComparableです。

IComparableではCompareToで

  • 自分より与えられた値のほうが小さいなら-1以下を
  • 自分より与えられた値のほうが大きいなら1以上を
  • 自分の値と与えられた値が等しいなら0を

返します。

こういうふうに比較ルールをつけることで自作クラス同士を比較可能にします。

実際に文字列の長さで比較可能にしたのがこちら

public class MyObject:IComparable
{
    public string hoge;
    public MyObject(string hoge)
    {
        this.hoge = hoge;
    }
    public int CompareTo(object obj)
    {
        MyObject myObj=(MyObject)obj;

        if (myObj.hoge.Length < this.hoge.Length)
        {
            //objのほうがちいさいとき
            return -1;
        }
        else if (myObj.hoge.Length > this.hoge.Length)
        {
            //objのほうがでかいとき
            return 1;
        }
        else
        {
            //objと等しい時
            return 0;
        }
    }
}

こういうふうにすることで Listコレクションに自作クラスをいれたときにSortメソッドでソートすることができます。

List<MyObject> collection = new List<MyObject>();
collection.Add(new MyObject("コカコーラ"));
collection.Add(new MyObject("ペプシ"));
collection.Add(new MyObject("おーいお茶"));
collection.Add(new MyObject("爽健美茶"));
collection.Add(new MyObject("伊右衛門"));
collection.Add(new MyObject("綾鷹"));
collection.Add(new MyObject("コカコーラゼロ"));

collection.Sort();

foreach (var i in collection)
{
    Console.WriteLine(i.hoge);
}

f:id:garicchi:20140911204701p:plain

また、BinarySearchメソッドをつかうことで高速な二分探索を行うこともできます。

IComparable

こちらはIComparableのジェネリック版です。特に違いはありませんが動作が若干早いらしいです。

public class MyObject:IComparable<MyObject>
{
    public string hoge;
    public MyObject(string hoge)
    {
        this.hoge = hoge;
    }

    public int CompareTo(MyObject other)
    {
        MyObject myObj = (MyObject)other;

        if (myObj.hoge.Length < this.hoge.Length)
        {
            //objのほうがちいさいとき
            return -1;
        }
        else if (myObj.hoge.Length > this.hoge.Length)
        {
            //objのほうがでかいとき
            return 1;
        }
        else
        {
            //objと等しい時
            return 0;
        }
    }
}

まとめ

  • IComparableは自作クラスのオブジェクト同士を比較可能にする
  • IComparableはCompareToで一定の規則にもとづいて整数値を返す
  • IComparableはIComparableのジェネリック版である