C# で、デリゲート (delegate) 使うメリットを考えてみます。
■ サンプルの概要
0 ~ 10 までの数字から特定の条件に合致する数字を出力します。具体的には次の仕様です。
- button 1 をクリックすると、2 で割り切れる数字だけをコピーします。
- button 2 をクリックすると、7 以上の数字だけをコピーします。
■ 一般的なサンプル (C#)
各ボタンから ListCopy メソッドを実行する際に、引数で処理の内容を決定しています。
従来のコーディング方法であれば、特に大きな問題は見当たりません。異なる処理を実行したいときには、フラグを渡して処理を変更させる方法は一般的です。
しかし、細かく見てみると、フラグ処理を 2 箇所で行っています。各ボタンイベントで個々のフラグを設定することは仕方ありません。これはアプリケーションの仕様なのですから。しかし、ListCopy メソッドの中で再びフラグの処理をしているのが気になります。仕様変更の際は、呼び出し元 (各ボタンイベント) と呼び出し先 (ListCopy) の両方を変更する必要があります。
また、フラグの内容も気になります。リテラルで 2 や 7 を直接渡すのはいい感じがしません。となると、定数を使うか?Enum を使うか?それとも、app.config に定義してから使うかを考えることになります。どの方法でもコード量が増加します。
private void button1_Click(object sender, EventArgs e) { ListCopy(2); } private void button2_Click(object sender, EventArgs e) { ListCopy(7); } private void ListCopy(int iFlag) { bool bRet = true; for (int i = 0; i < 11; i++) { switch (iFlag) { case 2: bRet = Num2(i); break; case 7: bRet = Num7(i); break; } if (bRet) Console.WriteLine(i); } } private bool Num2(int i) { return ((i % 2) == 0) ? true : false; } private bool Num7(int i) { return (i >= 7) ? true : false; }
■ デリゲートを使ったサンプル (C#)
ListCopy を実行する際の引数をフラグからデリゲートに変更しています。元々、呼び出す際のフラグでどのメソッドを実行するかは分かっています。それならば、そのメソッドを予め指定してやればよいだけです。このようにメソッドを引数に渡せる機能のデリケートの機能の一つです。
このように記述することで、重複したフラグ処理は不要になりました。ListCopy メソッドの中では、渡されメソッドを単に実行するだけなので、コード量が短くなります。
delegate bool LT(int i); private void button1_Click(object sender, EventArgs e) { ListCopy(new LT(Num2)); } private void button2_Click(object sender, EventArgs e) { ListCopy(new LT(Num7)); } private void ListCopy(LT NumMethod) { bool bRet = true; for (int i = 0; i < 11; i++) { bRet = NumMethod(i); if (bRet) listBox1.Items.Add(i); } } private bool Num2(int i) { return ((i % 2) == 0) ? true : false; } private bool Num7(int i) { return (i >= 7) ? true : false; }
結果
button1 クリック時
動作確認環境
Visual Studio 2015 Professional (C# 6.0)