レガシーコードからの脱却

レガシーな職場でも独学でどうにか頑張っていくブログです。

【お勉強記録】C#文法学び直し。デリゲート

デリゲート

delegate(デリゲート)はC#の型の一種で、メソッドへの参照を持つデータ型。 JavaScriptでfunctionも変数で受け渡しできるよっていうのと同じようなイメージを持っています(?)

using System;

namespace test
{
    class Program
    {
        static void Main(string[] args)
        {           
            Example_delegate.TestDelegate(3, 2);

            Console.ReadLine();
        }
    }

    public class Example_delegate
    {
        delegate int ExampleFunc(int x, int y);

        public static void TestDelegate(int x, int y) {
            ExampleFunc ef = Add;
            Console.WriteLine("メソッドAddを実行");
            Console.WriteLine(ef(x, y).ToString());

            ef = Sub;
            Console.WriteLine("メソッドSubを実行");
            Console.WriteLine(ef(x, y).ToString());

            ef = Mul;
            Console.WriteLine("メソッドMulを実行");
            Console.WriteLine(ef(x, y).ToString());
        
        }

        private static int Add(int x, int y) 
        {
            return x + y;
        }

        private static int Sub(int x, int y)
        {
            return x - y;
        }

        private static int Mul(int x, int y)
        {
            return x * y;
        }        

    }

}

実行結果は以下の通り

メソッドAddを実行
5
メソッドSubを実行
1
メソッドMulを実行
6

宣言したデリゲートと引数と戻り値の型が同じメソッドへの参照を持つことができます。

Funcデリゲート Actionデリゲート

型パラメータをつかってもっとシンプルに書くことができるようです。

さっきのやつをFuncを使って書き換えてみると、こんな感じですかね?

using System;

namespace test
{
    class Program
    {
        static void Main(string[] args)
        {
            Example_delegate.TestFunc(3, 2);

            Console.ReadLine();
        }
    }

    public class Example_delegate
    {        

        public static void TestFunc(int x, int y) {
            Func<int, int, int> func = Add;
            Console.WriteLine("メソッドAddを実行");
            Console.WriteLine(ef(x, y).ToString());

            func = Sub;
            Console.WriteLine("メソッドSubを実行");
            Console.WriteLine(ef(x, y).ToString());

            func = Mul;
            Console.WriteLine("メソッドMulを実行");
            Console.WriteLine(ef(x, y).ToString());
        
        }

        private static int Add(int x, int y) 
        {
            return x + y;
        }

        private static int Sub(int x, int y)
        {
            return x - y;
        }

        private static int Mul(int x, int y)
        {
            return x * y;
        }        

    }

}

Func<T, TResult>デリゲートは以下の構文になっているとのことです。

public delegate TResult Func<in T, out TResult>(
    T arg
)

メソッドの引数の方を順に指定していって、最後に戻り値の型を指定するってことのようです。

Actionは戻り値がないときに使用されます。

パーフェクトC#ではデリゲートの利用イメージとして

  1. 「イベントとイベントハンドラ
  2. 「スレッドとエントリポイント」
  3. 「スケルトンロジックの共通化」

の3つが出ています。

マルチスレッドのプログラムを書いた経験があまりないので、2はあまりイメージ付きません。これから勉強ですね…。