導入
自作クラスのリストを Sort() したら例外になった——それは「どちらが大きいか」のルールを型が持っていないからです。IComparable<T> は並べ替えの順序を、IEquatable<T> は等しさの判定を、型自身に持たせるインターフェースです。
図解
classDiagram
class IComparable~T~ {
+CompareTo(T other) int
}
class Money {
+int Yen
+CompareTo(Money other) int
}
IComparable~T~ <|.. Money
サンプル
var prices = new List<Money>
{
new Money(300), new Money(100), new Money(200)
};
prices.Sort(); // IComparable のルールで並ぶ
Console.WriteLine(string.Join(",", prices.Select(m => m.Yen))); // 100,200,300
class Money : IComparable<Money>
{
public int Yen { get; }
public Money(int yen) => Yen = yen;
// 負=自分が小さい / 0=同じ / 正=自分が大きい
public int CompareTo(Money? other) => Yen.CompareTo(other!.Yen);
}
IComparable<T>のCompareToが「並べ替えの順序」を定義する(Sort/OrderByが使う)IEquatable<T>のEqualsが「等しさ」を定義する(Containsなどが使う)- 数値・文字列など標準型はこれらを最初から実装している
やってみよう
CompareTo の中を other!.Yen.CompareTo(Yen) にひっくり返すと降順になります。並び順が反転することを確かめましょう。
演習
var items = new List<Box> { new Box(3), new Box(1), new Box(2) };
items.Sort();
Console.WriteLine(string.Join(",", items.Select(b => b.Size))); // 1,2,3
// TODO: Size の昇順で比較する IComparable<Box> を実装した Box を定義してください
___
- 期待される出力:
1,2,3
ヒント1を見る
class Box : IComparable<Box> { public int Size { get; } public Box(int s) => Size = s; public int CompareTo(Box? other) => Size.CompareTo(other!.Size); }
ヒント2を見る
昇順は「自分の値 .CompareTo( 相手の値 )」の向きです
まとめ
IComparable<T>は並べ替えの順序を型に持たせる(Sort/OrderBy)IEquatable<T>は等しさの判定を型に持たせるCompareToの戻り値は 負/0/正 で大小を表す
次回: 親のメンバーを「隠す」new修飾子と、親を呼ぶ base です。