連載

C#入門

第17回 処理を委譲するdelegate

(株)ピーデー
川俣 晶
2001/12/07


移譲先リストの変更

 delegateに含まれる移譲先リストは、いつでも追加削除できる。追加には「+演算子」や「+=演算子」を使い、削除には「−=演算子」を用いる。以下はリストの追加と削除を行うサンプル・ソースである。

 1: using System;
 2:
 3: namespace ConsoleApplication29
 4: {
 5:   delegate void Sample();
 6:   class Class2
 7:   {
 8:     private string name;
 9:     public Class2( string name )
10:     {
11:       this.name = name;
12:     }
13:     public void method()
14:     {
15:       Console.WriteLine(name);
16:     }
17:   }
18:   class Class1
19:   {
20:     static void Main(string[] args)
21:     {
22:       Sample samples = new Sample( new Class2("test1").method );
23:       Sample sample2 = new Sample( new Class2("test2").method );
24:       Sample sample3 = new Sample( new Class2("test3").method );
25:       Sample sample4 = new Sample( new Class2("test4").method );
26:       Console.WriteLine("call 1 method");
27:       samples();
28:       samples += sample2;
29:       samples += sample3;
30:       samples += sample4;
31:       Console.WriteLine("call 4 methods");
32:       samples();
33:       samples -= sample2;
34:       Console.WriteLine("call 3 methods");
35:       samples();
36:     }
37:   }
38: }
リストの追加と削除を行うサンプル・プログラム10
「−=演算子」によって、delegateの呼び出しリストから、登録されているメソッドを削除することができる。

 これを実行すると以下のようになる。

サンプル・プログラム10の実行結果
1つのdelegateに4つのメソッドを登録して呼び出した後、2番目のメソッドだけを削除して再度呼び出している。

 27行目の段階では、samplesには1つしかメソッドが登録されていないので、それだけが呼ばれる。しかし、32行目の段階では、4つのメソッドが登録されていて、それらのすべてが呼び出される。しかし、33行目で1つの移譲先を取り除いているので、35行目の段階では、3つのメソッドが呼び出されている。

delegate型の同一性

 delegateで委譲するメソッドは戻り値と引数が一致していればよいと書いたが、delegate型同士は、戻り値と引数が一致していても、同じとは見なされない。以下のサンプル・ソースはコンパイルできない誤った例である。

 1: using System;
 2:
 3: namespace ConsoleApplication30
 4: {
 5:   delegate void Sample1();
 6:   delegate void Sample2();
 7:   class Class1
 8:   {
 9:     public static void method()
10:     {
11:       Console.WriteLine("Hello!");
12:     }
13:     static void Main(string[] args)
14:     {
15:       Sample1 samples = new Sample1( Class1.method );
16:       Sample2 sample2 = new Sample2( Class1.method );
17:
18:       // エラー: 演算子 '+=' を 'ConsoleApplication30.Sample1' と'ConsoleApplication30.Sample2' 型のオペランドに適用することはできません。
19:       samples += sample2;
20:
21:       samples();
22:     }
23:   }
24: }
delegateの誤った使い方を示すサンプル・プログラム11
メソッドの戻り値と引数が一致していても、異なるdelegate型のインスタンスを合成することはできない。

 19行目のように、異なるdelegate型のdelegateインスタンスを1つのリストにまとめることはできない。たとえ、戻り値と引数が一致していても、である。

まとめ

 delegateは込み入ったメソッド呼び出しをスマートに解決する能力を秘めた、強力な機能である。クラスと継承を使って実現するのに比べれば、非常にコンパクトでスマートといえる。メソッド呼び出しのコードから呼び出し先に関する詳細情報を隠してしまうので、うまく活用すればソースコードがシンプルで読みやすくなる可能性もある。理解して使いこなすのもたいへんだと思うが、ぜひチャレンジしてみていただきたい。

 さて、次回はエラー処理のかなめとなる例外について取り上げたいと考えている。

 それでは次回もLet's See Sharp!End of Article


 INDEX
  第17回 処理を委譲するdelegate
    1.delegateとは何か
    2.staticなメソッドへの委譲
    3.戻り値と引数が合えば委譲できる
    4.delegateをオブジェクトとして使う
  5.移譲先リストの変更
 
「C#入門」


Insider.NET フォーラム 新着記事
  • 第2回 簡潔なコーディングのために (2017/7/26)
     ラムダ式で記述できるメンバの増加、throw式、out変数、タプルなど、C# 7には以前よりもコードを簡潔に記述できるような機能が導入されている
  • 第1回 Visual Studio Codeデバッグの基礎知識 (2017/7/21)
     Node.jsプログラムをデバッグしながら、Visual Studio Codeに統合されているデバッグ機能の基本の「キ」をマスターしよう
  • 第1回 明瞭なコーディングのために (2017/7/19)
     C# 7で追加された新機能の中から、「数値リテラル構文の改善」と「ローカル関数」を紹介する。これらは分かりやすいコードを記述するのに使える
  • Presentation Translator (2017/7/18)
     Presentation TranslatorはPowerPoint用のアドイン。プレゼンテーション時の字幕の付加や、多言語での質疑応答、スライドの翻訳を行える
@ITメールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)

注目のテーマ

Insider.NET 記事ランキング

本日 月間