|
■No57350 (TAKE さん) に返信
> 誰かdelegateの利点が自然に理解できるような
無茶ぶり? (^_^;)
> 例題をだしてもらえないでしょうか?
例題は思いつかないので、.NET 標準のデリゲートを使った話をしてみます。
たとえばデータの並びかえ。
幾つかの数値データを、
List<int> foo = new List<int>();
に格納してあるとして…これを並び替えるには、
foo.Sort();
とすれば良いですよね。List<T> ではなく配列なら、Array.Sort( 変数 ); です。
さて、これが数値型ではなく、自作クラス「社員」を格納していた場合はどうでしょう。
下記のようなケースです。
class 社員 {
public ushort 社員番号;
public string 氏名;
public 社員(ushort 社員番号, string 氏名) {
this.社員番号 = 社員番号;
this.氏名 = 氏名;
}
public override string ToString() {
return string.Format("{0,7} {1}", 社員番号, 氏名);
}
}
//===================================
List<社員> foo = new List<社員>();
foo.Add(new 社員(400, "EEEE"));
foo.Add(new 社員(100, "BBBB"));
foo.Add(new 社員(300, "AAAA"));
foo.Add(new 社員(200, "CCCC"));
foo.Add(new 社員(500, "DDDD"));
Console.WriteLine("--- ソート前 ---");
foo.ForEach(Console.WriteLine);
Console.WriteLine("--- 氏名昇順 ---");
//
// ここに、氏名昇順での並び替え処理を記述
//
foo.ForEach(Console.WriteLine);
Console.Write("Hit Any Key...");
Console.ReadKey();
//===================================
しかし Array クラスや List<T> は、データをどのように並び替えれば良いのか知りません。
そこで利用者側が「〜〜の順に並び替えてください」と指示をだし、Array や List<T> は
その指示に従ってデータを比較し、並び替えをおこなうという手順が必要になります。
そして、この比較方法を指定する方法として、IComparable<T> インターフェイスを
実装するという手法が用意されています。
class 社員 : IComparable<社員> {
int IComparable<社員>.CompareTo(社員 other) {
return 社員番号.CompareTo(other.社員番号);
}
// 以下、先ほどと同様なので省略
}
このようにしておくと、「foo.Sort();」で社員番号順に並び替えが行われます。
List<T> は、内部で上記のメソッドを呼び出して 社員インスタンスを比較し、
並び順を決定してくれます。
しかしこの方法は、並び順が一種類の場合は良いですが、複数の並び順を
切り替えられるように作るとなると、やや手間がかかってしまいます。
たとえば、氏名順に並び替えられるよう、
return string.CompareOrdinal(a.氏名, b.氏名);
を返すように作りたい場合、IComparable.CompareTo を実装するときに、
なんらかの if 文分岐を用意してやる必要がありますし、新しい並び順を
定義したい場合、社員クラス自体に手を加えなければなりません。
そこで、並び替えのための「比較結果を返すデリゲート」Comparison<T> を使ってみます。
(似たようなものに、検索に使われる Predicate<T> デリゲートというものもあります)
たとえば、呼び出し側でこのようなメソッドを用意しておき、
static int 氏名昇順(社員 a, 社員 b) {
return string.CompareOrdinal(a.氏名, b.氏名);
}
それを
foo.Sort(new Comparison<社員>(氏名昇順));
のように指定すれば、氏名の昇順にソートさせることができます。
こうすれば、社員クラス自体には手を加えることなく、並び順を
利用者側で自由に定義できるようになります。
この場合、デリゲートの指定に匿名メソッドを用いることもできますし、
Comparison<社員> 社員番号順 = delegate(社員 a, 社員 b) {
return a.社員番号.CompareTo(b.社員番号);
};
foo.Sort(社員番号順);
その匿名メソッドを直接埋め込んで
foo.Sort(delegate(社員 a, 社員 b) { return a.社員番号.CompareTo(b.社員番号); });
のように指定したり、さらにそれをラムダ式として
foo.Sort((a, b) => a.社員番号.CompareTo(b.社員番号) );
と短縮表記していく事もできます。
# 最近だと、Linq で OrderBy 指定するという手もありますけれどね。
|