はじめに
今回はC#のよく使うインターフェイスの一つであるIComparerについての記事になります。
前に取り上げたIComparable
とよく一緒に取り上げられたりします。
これらの使用用途の違いは、
IComparable
はソート方法が既に決まっているときIComparer
はソート方法が複数あり場合に応じて変更したいとき
に用いられるイメージです。
もっとちゃんと言うとIComparer
インターフェイスは比較処理と比較される対象を分離することができるところが特徴です。
では早速みていきましょう。
IComparerインターフェイス
IComparer
インターフェイスを実装することで2 つのオブジェクトを比較するメソッドを提供します。
IComparer インターフェイス (System.Collections) | Microsoft Docs
具体的に書くとIComparer
インターフェイスを実装しているクラスはCompareメソッド
を実装しなければなりません。
using System.Runtime.InteropServices; [ComVisible (true)] public interface IComparer { int Compare (object x, object y); }
public interface IComparer<in T> { int Compare (T x, T y); }
IComparer
とIComparer<T>
には定義からみても機能的に大差ありません。
ジェネリックの方はCompareメソッド
の引数が固定になりますが、むしろいろんなチェックなどを自前で実装しなくてよく楽なことが多いので、基本はジェネリックの方を使うとよいでしょう。
Compareメソッド
の返り値は以下のように定義しなければなりません。
- オブジェクトが引数で与えられたオブジェクトより前にあるなら0未満
- オブジェクトが引数で与えられたオブジェクトと同じ位置なら0
- オブジェクトが引数で与えられたオブジェクトより後にあるなら0より大きい
実際に使ってみる
配列を昇順・降順するサンプルを書いてみました。
Array.Sortメソッド
には引数にIComparer
を指定することができます。
class MainClass { static void Main() { // 1~10のランダムにした配列 var array = Enumerable.Range(1, 10).OrderBy(t => Guid.NewGuid()).ToArray(); // 昇順のソート Array.Sort(array, new AscendingComparer()); Console.WriteLine(string.Join(",", array)); // 降順にソート Array.Sort(array, new DescendingComparer()); Console.WriteLine(string.Join(",", array)); } // 前の方が小さくなるようする public class AscendingComparer : IComparer<int> { public int Compare(int x, int y) { return x - y; } } // 前の方が大きくなるように public class DescendingComparer : IComparer<int> { public int Compare(int x, int y) { return y - x; } } }
さいごに
これらのIComparer
,IComparer<T>
をより良く活用するために、Comparison<T>デリゲート
やComparer<T>クラス
・Comparer.Createメソッド
といったものが出てきています。
特にComparer<T>クラス
・Comparer.Createメソッド
あたりは触っていた方が良い気がするので、また暇があれば記事を書こうかなと思ってます。
ではまた。