独自に定義する型をコレクションがソートしたり検索したりするときのために、順序関係を必要とする場合がある。.NET Frameworkは、順序関係を実装するために2つのインターフェイスを提供している。IComparable<T>
とIComparer<T>
である。
IComparable
インターフェイスには、メソッドが1つだけ含まれる。CompareTo()
である。比較結果は以下のような戻り値によって表現される。
- 負の数: 現在のオブジェクト < 比較対象
- 0: 現在のオブジェクト = 比較対象
- 1以上: 現在のオブジェクト > 比較対象
新しめの.NET FrameworkのAPIはIComparable<T>
を使用するが、古いAPIの中にはIComparable
を使うものもある。そのため、IComparable<T>
を実装する際は、IComparable
も実装すべきである。
以下は、IComparable<T>
およびIComparable
の実装例。
public struct Customer : IComparable<Customer>, IComparable
{
private readonly string _name;
public Customer(string name)
{
_name = name;
}
public int CompareTo(Customer other)
{
return string.Compare(_name, other._name, StringComparison.Ordinal);
}
public int CompareTo(object obj)
{
if (!(obj is Customer))
throw new ArgumentException("Argument is not a customer", nameof(obj));
var other = (Customer) obj;
return string.Compare(_name, other._name, StringComparison.Ordinal);
}
}
さらに、比較の方法自体をカスタマイズしたい場合は、IComparer<T>
を使うことができる。
private readonly double _revenue;
private static readonly Lazy<RevenueComparer> RevComp =
new Lazy<RevenueComparer>(() => new RevenueComparer());
public static IComparer<Customer> RevenueCompare => RevComp.Value;
private class RevenueComparer : IComparer<Customer>
{
public int Compare(Customer left, Customer right)
{
return left._revenue.CompareTo(right._revenue);
}
}
このようにすれば、Customer.CompareTo()
でnameによる比較を提供しつつ、Customer.RevenueCompare.Compare()
でrevenueに基づいた比較も提供することができる。