【C# Delegate, Func】別の関数を引数とした関数作成

## 目的
関数を引数とする関数を作成する
### コンパイル環境
[C# Online | ブラウザでプログラミング・実行ができる「オンライン実行環境」| paiza.IO](https://paiza.io/ja/projects/new?language=csharp)
アクセス先に表示されているプログラムを全て削除し、以下に記載しているコードを貼り付ければ動作します。
### 関数を引数に取る方法
2通りの方法で記載しております。

1. 関数の引数用に`Delegate`を定義し、関数の引数とする
2. 関数の引数に`Func`で関数定義を設定し、関数の引数とする

※各番号に対応する箇所を`/// --- xxxxx --- ///`形式のコメントで囲っております。

### コード
```C#
// Funcを利用するためにusingで呼び出し
using System;

public class DelegateTest{

    /* 
     * 関数の引数として利用したい関数を作成する
     *    1つのDelegateで全ての関数に対応するため、
     *    すべての関数で同一型、同一個数、同一戻り値の引数を指定しています。
     *    (引数: double, double / 戻り値 double)
    */

    // 和
    private static double Sum(double x, double y)
    {
        return x + y;
    }

    // 差
    private static double Balance(double x, double y)
    {
        return x - y;
    }

    // 積
    private static double Product(double x, double y)
    {
        return x * y;
    }

    // 商
    private static double Devide(double x, double y)
    {
        return x / y;
    }

    /// --- [↓↓↓] 1. 関数の引数用にDelegateを定義し、関数の引数とする場合の処理 [↓↓↓] --- ///
    /* 
     * 関数の情報を入れたDelegateを作成する
     *    上記で定義した関数を利用できるように以下の情報を指定したDelegateを作成します
     *    (引数: double, double / 戻り値 double)
    */
    delegate double CFunc(double x, double y);
    
    /* 
     * 関数を引数にとるラッパー関数を作成する
     *    関数の引数に定義したDelegate、引数として与える関数用の引数群を設定し、
     *    上記で定義したDelegateを呼び出せるようにしています。
     *    (引数: CFunc(引数とする関数の情報を付与したDelegate), double, double / 戻り値 なし)
    */
    private static void CallDelegateFunc(Func<double, double, double> func, double x, double y)
    {
        // 引数の関数を呼び出し、結果を文字列として取得
        string result = func(x, y).ToString();
        // メソッド名取得
       string methodName = func.Method.Name;
        System.Console.WriteLine($"Method:{methodName} / Result:{result}");
    }
    /// --- [↑↑↑] 1. 関数の引数用にDelegateを定義し、関数の引数とする場合の処理 [↑↑↑] --- ///

    /// --- [↓↓↓] 2. 関数の引数にFuncで関数定義を設定し、関数の引数とする場合の処理 [↓↓↓] --- ///
    /* 
     * 関数を引数にとるラッパー関数を作成する
     *    関数の引数にFuncで関数を定義し、引数として与える関数用の引数群を設定し関数呼び出しを行います。
     *    Func<double, double, double> <- 1つ目、2つ目のdoubleは、関数の引数。 3つ目のdoubleは関数の戻り値。
     *    (引数: Func<double, double, double>, double, double / 戻り値 なし)
    */
    private static void CallFunc(Func<double, double, double> func, double x, double y)
    {
        // 引数の関数を呼び出し、結果を文字列として取得
        string result = func(x, y).ToString();
        // メソッド名取得
        string methodName = func.Method.Name;
        System.Console.WriteLine($"Method:{methodName} / Result:{result}");
    }
    /// --- [↑↑↑] 2. 関数の引数にFuncで関数定義を設定し、関数の引数とする場合の処理 [↑↑↑] --- ///

    /* 
     * 関数の挙動を確認する
     *     各関数を引数としてラッパー関数を呼び出し、正常に動いているか確認します。
    */
    public static void Main(){
        // Delegateを引数にしたラッパー関数、引数内でFuncを定義したラッパー関数で同一結果になることを確認する
        System.Console.WriteLine("各関数の呼び出し結果");
        CallDelegateFunc(Sum, 10, 1.5);
        CallFunc(Sum, 10, 1.5);
        CallDelegateFunc(Balance, 10, 1.5);
        CallFunc(Balance, 10, 1.5);
        CallDelegateFunc(Devide, 10, 1.5);
        CallFunc(Devide, 10, 1.5);
        CallDelegateFunc(Product, 10, 1.5);
        CallFunc(Product, 10, 1.5);

        /* 
         * ラムダ式を関数として与えることもできます
         *      ラムダ式の説明
         *      (a, b) => a + b
         *        ①    ②    ③
         *        
         *      ① 「(a, b)」 <- 無名関数で引数を2つ取ることを指定しています
         *      ② 「=>」     <- 左辺の引数を用いて右辺の処理を行い、演算結果を戻します
         *      ③ 「a + b」  <- 関数の処理内容を定義しています
         *      
         *      処理内容としては、①で引数を2つ取りa,bに格納し、③でa+bを行った結果を戻す関数を定義しています。
         *      (上記ラムダ式はコードの11行目で定義したSum関数と同一の処理を行っています)
        */
        CallDelegateFunc((a, b) => a + b, 10, 1.5);
        CallFunc((a, b) => a + b, 10, 1.5);
    }
}
```
### 最後に
記事のコードでは、Delegate関数の型を定義する便利なハコ、というザックリとした認識で使用しております。
「Delegateの使い方おかしいんじゃない？」「自分の場合はこうしている」等のご指摘、ご意見をいただけると嬉しいです。

### 更新履歴
* コメントにてラッパ―関数の引数に`Func`を定義する手法を教えていただいたので、記事にFuncを利用した場合の処理を追加しました

### 参考サイト
#### デリゲート
[第17回 処理を委譲するdelegate](http://www.atmarkit.co.jp/fdotnet/csharp_abc/csharp_abc_017/csharp_abc01.html)
[デリゲートを引数に与える関数でラムダ式を利用する (C#プログラミング)](https://www.ipentec.com/document/csharp-simple-lambda-expressions-using-delegate-parameter)
[デリゲート](https://ufcpp.net/study/csharp/sp_delegate.html)

#### Func
[Func<T, TResult> , Action<T> デリゲートとは？ (C#プログラミング)](https://www.ipentec.com/document/csharp-delegate-func-action-type)

#### 文字列表示処理
[【C#】string.Format() をやめて $"{}"（文字列補間式）を使う](https://qiita.com/Nossa/items/c2226232b31d7665267f)

#### 関数名取得処理
[メソッド名を文字列で取得【C#】](http://kan-kikuchi.hatenablog.com/entry/GetMethodName)