delegateを学ぼう

using System;

namespace DelegateL2
{
    //delegate を定義 引数string 戻り値void
    delegate void Decorate(string s);
    class Program
    {
        
        static void Main(string[] args)
        {
            string str = "Hello";
            //デリゲートにメソッド登録
            Decorate dec = Star;
            //実行
            dec(str);
            //デリゲートのメソッド付け替え
            dec = Atsign;
            dec(str);
            //追加登録
            dec += Star;
            dec(str);
            //解除
            dec -= Atsign;
            dec(str);
            //引数がstring一つ、戻り値がvoidのメソッドなら登録できる。
            dec = Console.WriteLine;
            dec(str);
        }
        //引数がstring一つ戻り値がvoidのメソッド定義
        static void Star(string s){
            Console.WriteLine($"*{s}*");
        }
        static void Atsign(string s){
            Console.WriteLine($"@{s}@");
        }
    }
}


デリゲートはメソッドの引数に指定できる。

using System;

namespace DelegateL2
{
    //delegate を定義 引数string 戻り値void
    delegate void Decorate(string s);
    class Program
    {
        
        static void Main(string[] args)
        {
            String str = "Hello";
            //デリゲートを登録
            StrDecorate(str, Star);
            //匿名型で登録
            StrDecorate(str, delegate (string s) { 
                Console.WriteLine($"@{s}@");
            });
            //ラムダ式
            StrDecorate(str, (string s) => { Console.WriteLine($"@{s}@"); });
            //引数の型は暗黙推論されるので省略可能、引数が一つの場合()も省略可能、文が一つの場合{}は省略可能、
            StrDecorate(str, s => Console.WriteLine($"@{s}@"));

            string result=StrDecorate2(str, s => $"@{s}@");
            Console.WriteLine(result);

           
        }
        static void StrDecorate(string str,Decorate dec){
            dec(str);
        }
        static void Star(string s){
            Console.WriteLine($"*{s}*");
        }
        //自作のdelegateを作らなくても標準ライブラリでよく使うデリゲートは用意されている。
        //以下はstringを引数で受け取ってstringを返すdelegate
        static string StrDecorate2(string str,Func<string,string> func){
            return func(str);
        }

    }
}


Q
以下の処理を順番に実現しよう。

  1. intの引数を2個戻り値がintのdelegate MathFuncを作成せよ
  2. MathFuncの仕様を満たすメソッドで二つの整数の和を返却するメソッドPlusを作成せよ。
  3. メインメソッドでMathFunc型の変数mfを用意しそこにPlusメソッドを登録せよ。
  4. 上記を利用して5と2の和を出力せよ。
  5. int型の引数2個とMathFunc型の引数1個戻り値intのメソッドCalcを作成せよ。メソッドの内容は二つのintの値をMathFuncで処理した値を返すメソッドすること。
  6. Calcに10と2とPlusを渡して結果を出力せよ。
  7. Calcの第三引数に匿名メソッドを用い、10と2の積を計算し出力せよ。
  8. Calcの第三引数にラムダ式を用いて10と2の商を求め出力せよ。
  9. Calcを用い二つの整数(10と2)の大きい方を表示せよ。

[実行例]

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace DelegateSample
{
    delegate int MathFunc(int x, int y);
    class Program
    {
        static void Main(string[] args)
        {
            MathFunc mf = Plus;
            Console.WriteLine(mf(5, 2));
            Console.WriteLine(Calc(10, 2, Plus));
            Console.WriteLine(Calc(10, 2, delegate (int x, int y) { return x * y; }));
            Console.WriteLine(Calc(10, 2, (x, y) => x / y));
            Console.WriteLine(Calc(10, 2, (x, y) => x > y ? x:y));
            //Console.WriteLine(Calc(10, 2, Math.Max));
        }
        static int Plus(int x,int y)
        {
            return x + y;
        }
        static int Minus(int x,int y)
        {
            return x - y;
        }
        static int Calc(int x,int y,MathFunc mf)
        {
            return mf(x, y);
        }
        
    }
}

今回は自分でデリゲートを用意したがライブラリにすでにあるデリゲートを利用すると上記Calcは以下のようにかける

static int Calc(int x,int y,Func<int,int,int> mf){}

ライブラリが用意しているよく使われるdelegate

Func //引数なし、戻り値int
Func //引数string 1 戻り値string
Func //引数がint,string 戻り値がstring
Action //引数も戻り値もなし
Action void 引数1個
Action void 引数2個