Taskを学ぶ前のあなたに-ActionとFunc理解してます?-

# 初めに
　だんだんとプログラミングに慣れてくると並列処理について知ることになると思います。C#で言うならば`Parallel.For`だったり`Task`だったりです。この二つを学ぼうとするとき障壁になるの`Action<>`や`Func<>`といった、なんかよくわからないクラスたちです。
 　一言で言ってしまうとこれらのクラスはDelegate型と非常に密接に関わっています。
  この記事でそのもやもやを少しでも解消できたら幸いです。
　なお~~サボりたい~~見やすさ的に最低限のサンプルコードだけを載せます。
# Delegate型って何？
　簡単に言ってしまうとメソッドの参照を格納することができる型です。例を見てみましょう。一緒に手を動かしてみるとさらに理解は深まりますよ!
```C#:Program.cs
//namespaceなどは省略しています。
        static void Main(string[] args)
        {
            Program p = new Program();

            SampleDelegate d1 = new SampleDelegate(p.G);//p.G()じゃない
            d1 += p.H;
            d1.Invoke();

        }
        
        public delegate void SampleDelegate();//delegate型は一種のクラスのようなもの
        
        public void G()
        {
            Console.WriteLine("G");
        }
        public void H()
        {
            Console.WriteLine("H");
        }
        
```
このコードを実行するとコンソールに
```C#:コンソール
G
H
```
と表示されるはずです。コードを見たらわかりますが先に `P.G`と代入しています。ここを先に`P.H`を代入すれば`.Invoke()`したとき、先に`P.H`が実行されます。他にも`-=`を利用するとすでに代入されているメソッドの参照を消せたりするので、まあそこらへんは自分で調べてください。(丸投げ)

# そもそもどこでDelegate型が使われるのか
　あるボタンのクリックイベントハンドラに関数を渡すコードです。
 ```C#:Background.cs
 //xamlなどで<Button Name="button">みたいにすれば
 button.Click += Tekitou();
 ```
 ここで`.Click`に注目してください。これは~~厳密に言わなくても~~`event`です。しかし`event`は`delegate`を基にして作ったものなので同じような動作をします。これはあくまで一例なのでほかにも探してみてください。(丸投げPart2)

 # いちいちDelegate型を宣言するのがだるい
 　見ての通り、戻り値によって宣言する必要があります。
  ```C#:Sample.cs
  //void関数用
public delegate void SampleDelegate();
  //int関数用
public delegate int SampleDelegate2();
  //string関数用
public delegate string SampleDelegate();
  ...
  ```
  :scream: となります。ここに関数へ渡すための引数のことも考えるとさらに定義が必要となり、
  :scream: :scream: :scream:となります。

  
Q.では頭のいい人たちはどうしたのか。
   A.ジェネリック型で使いまわせるAction<>とFunc<>を定義しよう!:v:
# Actionについて
　これは主に**戻り値**のない関数の参照を格納するためにあります。
 ```C#:Sample.cs
        static void Main(string[] args)
        {
            Action<string,string,string> action = new Action<string, string, string>(S);
            //action += S2;
            action.Invoke("a", "b", "c");

        }

         public static void S(string a,string b, string c)
        {
            Console.WriteLine(a);
            Console.WriteLine(b);
            Console.WriteLine(c);
        }

        public static void S2(string a, string b)
        {
            Console.WriteLine(a);
            Console.WriteLine(b);
        }
 ```
 ```C#:コンソール
 a
 b
 c
 ```
　 Actionの<>の中はactionが参照に持つ関数へ渡す引数です。コードではstring型を第三引数まで取っています。そして関数`S(string a,string b, string c)`に注目してください。これもstring型を第三引数まで取っています。Action<>と引数が一致しない場合、その関数の参照をactionに渡すことはできません。
 　試しにactionへS2の参照を渡してみてください。必ずエラーが起きます。これは後述する`Func<>`でも同様です。

 # Funcについて
 `Func<>`も`Action<>`とほぼ同じ動作をしますが、
 ```C#
 Func<string,string,string> func //~~~省略
 ```
 このように書かれたとき、`Func<>`の**最後の引数**は`func`が参照に持つ関数の**戻り値**となります。つまり`Func<>`は**戻り値がある**関数の参照を格納するためにあります。コードで見てみましょう。
 ```C#:Sample.cs
        static void Main(string[] args)
        {
            Func<string,string,string,string> func = new Func<string, string, string, string>(S);
            func += S2;

            var results = new List<string>();//戻り値を取得するためのList
            foreach (var item in func.GetInvocationList())
            {
                if(item is Func<string, string, string, string> f)
                {
                    var result = f.Invoke("a","b","c");
                    Console.WriteLine(result.ToString());
                }
            }

        }

        public static string S(string a,string b,string c)
        {
            return a + b + c;
        }

        public static string S2(string a, string b,string c)
        {
            return c + b + a;
        }
    
 ```
  ```C#:コンソール
abc
cba
 ```
　見ての通り戻り値があるため`Action`より複雑になります。また`foreach`内の処理は書き方がいくらかあるので試してみてください。

 # 最後に
 　こう考えると`Action`や`Func`はとても便利なものですね。これらは`Task`などで遊ぶ際でも出てくるのでみっちり抑えておいて損はないでしょう。この記事で少しでもモヤモヤがなくっていると幸いです。お疲れさまでした。