【Action, Func】定義済みデリゲートについて

【Action, Func】定義済みデリゲートについて

おはようございます。

先日デリゲートに関して記事を書きましたが、今回は C#の機能として予め定義されているデリゲート「定義済みデリゲート」に関してまとめました。

定義済みデリゲートとは?

前回の記事で、デリゲートとはデリゲートとは関数を格納できる特殊なデータ型の変数であるということを説明してきました。

そして、引数や戻り値を指定するパターンもありました。

実際に書いてみると分かるのですが、毎回delegate型を定義してメソッドを代入してインスタンス化して…、と結構面倒になってきます。

そこで、デリゲートをより使いやすい形で定義されたものが C#の機能で用意されています。これを定義済みデリゲートと言います。

定義済みデリゲートには、ActonFuncの 2 つがあります。

Action

Action戻り値を返さないデリゲートです。Actionはアセンブリ内で以下のように定義されています。

public delegate void Action<in T>(T obj);

Visual Studio で新しくクラスを作成した時、System の名前空間はusingされているため外部のクラスを読み込むことなく使用することができます。

まずは簡単なコードで Action の定義から実行まで確認していきます。

using System;

public class Hello{

  public static void Main(){

    // 1. Actionを定義し、メソッドを代入
    Action acFunc = func1;

    // 3. Actionを実行
    acFunc();
  }

  // 2. Actionに格納するメソッドを定義
  static void func1()
  {
    Console.WriteLine("Actoin func1 Execute");
  }
}

デリゲートの宣言をすることなくメソッドが呼び出せています。

また、ラムダ式を使うことで現状のコードをコンパクトにまとめることができます。

using System;

public class Hello{

  public static void Main(){

    // ラムダ式で関数を記述
    Action acFunc = () => Console.WriteLine("Actoin func1 Execute");

    acFunc();
  }
}

引数を定義する場合

Action に格納するメソッドに引数を渡す場合は、Action 宣言時にパラメータを指定しておく必要があります。

先程のサンプルコードに引数を渡せるように書き換えてみます。

using System;

public class Hello{

  public static void Main(){

    // パラメータにint型を定義
    Action<int> acFunc = func1;

    acFunc(1);
  }

  static void func1(int value)
  {
    Console.WriteLine("Actoin func1 Execute : {0}", value);
  }
}

また、今回指定した引数は 1 つだけですが 16 個まで指定することができます。


  public static void Main()
  {
    Action<T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16> func = func;
  }

  static void func1(int value1, int value2, int value3, ...)
  {
    //
  }

Func

Actonが戻り値を返さないのに対して、Funcは戻り値を返す定義済みデリゲートになります。

Funcはアセンブリ内で以下のように定義されています。

// T: メソッドのパラメーターの型。
// TResult: メソッドの戻り値の型。
// arg: メソッドのパラメーター。
public delegate TResult Func<in T, out TResult>(T arg);

パラメーター T は、Funcに格納したメソッドに渡す引数の型を指定します。TResult は、Funcに格納したメソッドの戻り値の型を指定します。

Actionと同様に最大 16 個まで引数を指定する事ができます。

サンプルコードで実装方法を見ていきます。

using System;

public class Hello {
    public static void Main() {

      // Funcを定義
      Func<int, string> sayMethod = SayMessage;

      Console.WriteLine(sayMethod(5));
      // 1回目のメッセージ
      // 2回目のメッセージ
      // 3回目のメッセージ
      // 4回目のメッセージ
      // 5回目のメッセージ
      // メッセージが終了しました。
    }

    // Funcに渡すメソッドを定義
    public static string SayMessage(int num)
    {
      for(int i = 0; i < num; i++){
        Console.WriteLine($"{i + 1}回目のメッセージ");
      }

      return "メッセージが終了しました。";
    }
}

Funcにパラメータを一つだけ指定した場合は、引数なしの戻り値ありのパターンになります。

public delegate TResult Func<out TResult>();

今回はラムダ式でメソッドを渡してみます。

using System;

public class Hello {
    public static void Main() {

      Func<string> sayMethod = () => "メッセージが返ってきました。";

      Console.WriteLine(sayMethod());
      // メッセージが返ってきました。
    }
}

実際にコードを書いてみると、ActionFuncも使い方は似ていることが分かります。

まとめ

  • 定義済みデリゲートとは、デリゲートをより簡単に記述できるように C#側で用意されている機能のこと。
  • Actionは引数を持つことが出来るが、戻り値は返さない
  • Funcは引数も戻り値も返すことが出来る。定義時のパラメータが一つだけのときはTResult型を返すメソッドを定義する。

参考